注意,該頭文件僅在C++11中標准才開始出現。
簡介
與語言內置的數組一樣, array類模版支持幾乎所有內置數組包含的特性:
- 順序的(sequence)
- 內存連續的(contiguous storage)
- 固定大小的(fixed-size)
那既然與內置數組一樣,為什么還要定義這樣一個模版呢?C++委員會是想造輪子嗎(-_-)?當然不是!
為什么需要array?
array模版類實際上是內置數組的聚合,外加一層封裝。正是由於這層接口,才使得數組能與STL接軌,真正成為一個container。
Container接口
- array::size
- array::back
- array::front
- array::empty
- array::fill
- ...
簡單通用的array接口,讓數組使用起來更加得心應手。 例如size()成員函數返回數組的大小,在內置數組中則只能查看數組定義或者借助外部函數。
Interator模式接口(姑且讓我這么叫吧)
- array::begin
- array::end
- array::cbegin
- array::cend
- array::rbegin
- array::rend
- array::crbegin
- array::crend
解決語法不一致性
Iterator作為C++中溝通Algorithm與Container的橋梁,起着不可或缺的作用。然而內置類型不支持迭代器的概念,雖然對於算法來說有合適的重載能夠解決這個問題,但在語法上存在明顯的差別(vec為vector
for_each(vec.begin(), vec.end(), [](int i)
{
// something
});
for_each(arr, arr + 3, [](int i)
{
// something
});
其實不需要變量定義聲明就可以猜到,vec是container而arr不是。 這也許會阻礙代碼后期的重構與修改。使用array類模版的話就不會存在這種問題,統一的語法,多棒!
Bound Check
我們都知道,C++沿襲了C語言的設計,在access數組元素時不對數組變量進行邊界檢查。array解決了這個問題,在元素讀寫越界時會拋出異常。
差異性
與內置數組的差異
array與內置數組的一個明顯的差異就是----允許空數組的定義。
至於為什么要允許這樣一個特性,也許是:
- 讓空數組保持遍歷一致性。
- 讓array容器隱式地支持清空(畢竟作為一個fixed-size container,它沒有對應的clear操作)。
然而,空數組在語義上是不允許解引用的,因此在使用時規避那些需要解引用的操作。
與其他容器的差異
該方面的差異主要體現在swap成員函數上。就像我們知道的,其他容器調用swap函數時,為了保證高效,該函數實際上執行的操作相當於交換指向實際容器內容的指針。但是array的swap函數卻是進行逐成員交換,這也許是為了保持與內置數組相同的性質----數組地址不可變。
出於上述語義上的差別,array與其他容器的迭代器,在swap后會有不同的結果(深色方框代表容器對象, 方框內文字代表容器內容; 箭頭代表迭代器變量, 都指向頭元素):
swap前:
swap后:
從圖上看更為直接:
- array模版類對象只是交換了內容而已,兩個迭代器的值都未變。
- 其他容器對象不僅交換了內容,連迭代器的關聯性都改變了(實際上,迭代器的值(即關聯的內容)也沒變,但關聯的對象變了)。
Tuple接口
array還提供了一套獨特的tuple接口,使其能夠像使用元組那樣使用。 當然,這種可能性的前提是它本身就非常像元組。
這種特性是通過重載tuple接口的get函數,並且特化tuple_element和tuple_size類模版實現的。