如果你是STL的慣用者,且對(duì)效率持有莫大的興趣,你可能會(huì)對(duì)原生數(shù)組而不能優(yōu)雅的與 STL 算法結(jié)合而感到不滿和懊惱,你充其量可以這樣使用:
int nArray[4] = {1,2,3,4};
const int Len = sizeof( nArray ) / sizeof( int );
int nCount = std::count( nArray, nArray + Len, 3 );
然而你不肯運(yùn)用其他如 swap 等算法,數(shù)組是一個(gè)小型集合, 不能直接賦值。可能在模板中你更渴望有直接賦值的要求:
int nArray[4] = {1,2,3,4};
int nArray2[4] = nArray; // 這種優(yōu)雅的語法實(shí)在比 memcpy 等更具有觀賞性
std::swap( nArray, nArray2 ); // 適應(yīng)這種算法也更通用
幸而,boost提供了這樣一個(gè)物件: array, 說到底,array 只是原生數(shù)組的淺薄包裝而已,你甚至可以像原生數(shù)組那樣直接以大括號(hào)形式的賦值方式賦值:
array <int, 2> array = {{1,2}};
array <int, 2> array = {1,2}; // 顯然大部分編譯器已經(jīng)支持一個(gè)大括號(hào)的初始化了
這種賦值方式的技術(shù)要求是:
1. 不允許有用戶定義的構(gòu)造函數(shù)( 可以有析構(gòu) )
2. 不允許有 private 和 protected 的數(shù)據(jù)成員 ( 可以有 static 成員 )
3. 不允許有 父類
4. 無虛函數(shù)
從 C++ 對(duì)象模型角度來說,其結(jié)構(gòu)在內(nèi)存中是連續(xù)的一段,沒有額外的其他東西如虛表指針.
下面是其簡單定義:
template<class T, std::size_t N>
class array {
public:
T elems[N]; // 被包裝之原生數(shù)組
public:
// 類型定義
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// 迭代器支持
iterator begin() { return elems; }
iterator end() { return elems+N; }
// 反向迭代器支持
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
// 操作符[]
reference operator[](size_type i)
{
BOOST_ASSERT( i < N && "out of range" );
return elems[i];
}
// 帶有檢查的 at()
reference at(size_type i) { rangecheck(i); return elems[i]; }
const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
// front() 和 back()
reference front()
{
return elems[0];
}
reference back()
{
return elems[N-1];
}
// 大小為常量, 提供了 enum 來支持模板編程
static size_type size() { return N; }
static bool empty() { return false; }
static size_type max_size() { return N; }
enum { static_size = N };
// swap (線性復(fù)雜度)
void swap (array<T,N>& y) {
std::swap_ranges(begin(),end(),y.begin());
}
// direct access to data (read-only)
const T* data() const { return elems; }
T* data() { return elems; }
// use array as C array (direct read/write access to data)
T* c_array() { return elems; }
// 允許類型轉(zhuǎn)換的賦值
template <typename T2>
array<T,N>& operator= (const array<T2,N>& rhs) {
std::copy(rhs.begin(),rhs.end(), begin());
return *this;
}
// 數(shù)組填充某一值
void assign (const T& value)
{
std::fill_n(begin(),size(),value);
}
// 檢測(cè)區(qū)間
static void rangecheck (size_type i) {
if (i >= size()) {
throw std::out_of_range("array<>: index out of range");
}
}
};
當(dāng) N = 0 時(shí), 像elem[0]這樣的語法是錯(cuò)誤的,故以偏特化。內(nèi)部去掉了 T elems[N]; 大部分接口只是為了統(tǒng)一,內(nèi)部并未實(shí)作,頂多是拋出異常。
另外,一些有用的協(xié)助函數(shù),主要是比較函數(shù): ==, <, !=, >, <=, >=. 還有一個(gè)全局的swap,內(nèi)部主要調(diào)用array內(nèi)部的swap實(shí)現(xiàn):
// swap()
template<class T, std::size_t N>
inline void swap (array<T,N>& x, array<T,N>& y) {
x.swap(y);
}
瑕疵:
不過,我們只有顯示的提供給數(shù)組一個(gè)大小,不能再像下面一樣使用編譯器來替我們工作了:
而只有這樣:
array<int, 5> arr = {1,2,3,4,5};
另外,像 char 這樣的特殊元素, 我們就不免小心(見下篇)。
不過,比起array之功,這點(diǎn)瑕疵也完全可以忽略。