標籤:vector deque bitset
作為一個STL容器,vector<bool>只有兩點不對。首先,它不是一個STL容器。其次,它並不儲存bool。除此之外,一切正常。
一個對象要成為容器,就必須滿足C++標準中列出的所有條件,其中一個條件是,如果c是包含對象T的容器,而且c支援operator[],那麼下面的代碼必須能夠被編譯:
T *p = &c[0];
換句話說,如果用operator[]取得了container<T>中的一個T對象,那麼就可以通過取它的地址得到一個指向該對象的指標。所以,如果vector<bool>是一個容器,那麼下面這段代碼必須可以被編譯:
vector<bool> v;
bool *pb = &v[0];
但是它不能編譯。不能編譯的原因是,vector<bool>是一個假的容器,它並不真的儲存bool,相反,為了節省空間的,它儲存的是bool的緊湊表示。在一個典型的實現中,儲存在“vector”中的每個“bool”僅佔一個二進位位,一個8位的位元組可容納8個“bool”。在內部,vector<bool>使用了與位域一樣的思想,來表示它所儲存的那些bool;實際上它只是假裝儲存了這些bool。
位域與bool相似,它只能表示兩個可能的值,但是在bool和看似bool的位域之間有一個很重要的區別:我們可以建立一個指向bool的指標,而指向單個位的指標則是不允許的。指向單個位的引用也是被禁止的,這使得在設計vector<bool>的介面時產生了一個問題,因為vector<T>::operator[]的返回值應該是T&.如果vector<bool>中所儲存的確實是bool,那麼這就不是問題。但由於實際上並非如此,所以vector<bool>::operator[]需要返回一個指向一個單個位的引用,而這樣的引用並不存在。
當我們需要vector<bool>時,我們有兩種選擇可以做:
用deque<bool>。deque幾乎提供了vector所提供的一切(可以看到的省略只有reserve和capacity),但deque<bool>是一個STL容器,而且它確實儲存bool。當然,deque中元素的記憶體不是連續的,所以你不能把deque<bool>中的資料傳遞給一個期望bool數組的C API,但對於vector<bool>,我們也不能這麼做,因為沒有一種可移植的方法能夠得到vector<bool>中的資料。
選擇bitset。bitset不是STL容器,但它是標準C++庫的一部分。與STL容器不同的是,它的大小(即元素的個數)在編譯時間就確定了,所以它不支援插入和刪除元素。而且,因為它不是一個STL容器,所以它不支援迭代器。但是,與vector<bool>一樣,它使用了一種緊湊表示,只為所包含的每個值提供一個空間。它提供了vector<bool>特有的flip成員函數,以及其它一些特有的、對位的集合有意義的成員函數。