做為一個(gè)STL容器,,vector<bool>有兩個(gè)問題.第一,,它不是一個(gè)真正STL容器,,第二,它并不保存bool類型. 除此以外,,并沒有太多東西與本節(jié)題目有關(guān)(譯注,,還不夠多嗎)一個(gè)東西不能成為一個(gè)STL容器,只因?yàn)闀?huì)有人說(shuō)它是一個(gè)(譯注,:( ).一個(gè)東西要成為STL容器,必須滿足所有 列于C++標(biāo)準(zhǔn)23.1節(jié)的容器要求.在這些要求中,有這樣一條:如果C是一個(gè)T類型元素容器,并且C支持operator[] 那么以下代碼必須能夠編譯: T *p = &c[0]; // initialize a T* with the address // of whatever operator[] returns 換句話說(shuō),如果你使用operator[]來(lái)得到Container<T>中的一個(gè)T對(duì)象,你可以對(duì)它取地址從而得到一個(gè)指針. (假設(shè)T沒有重載opeartor&.譯注:原句為This assumes that T hasn't perversely overloaded operators. 從意譯)因此,如果vector<bool>可能成為容器,那么,這些代碼必須編譯通過: vector<bool> v; bool *pb = &v[0]; // initialize a bool* with the address of // what vector<bool>::operator[] returns 但是它不能編譯.不能的原因是vector<bool>是一個(gè)偽容器(pseudo-container),它并不保存真正的bool,而是 打包bool以節(jié)省空間.在一個(gè)典型的實(shí)現(xiàn)中,每一個(gè)"bool"保存在"vector"中都是一個(gè)"bit",8-bit的一個(gè)字節(jié) 將保存8個(gè)bool.從內(nèi)部來(lái)看,vector<bool>使用了與位域(bitfields)相同的思想來(lái)表示需要保存的bool值. 與bool值相似,位域也只有兩個(gè)值,但有它倆之間有一個(gè)重要的不同:可以創(chuàng)建指向真正的bool型的指針,但指 向單獨(dú)一位的指針卻非法. 考慮到指向單獨(dú)一位的指針非法,這為vector<bool>的設(shè)計(jì)擺出了難題.因?yàn)関ector<T>::operator[]的返回值 是T&類型.如果vector<bool>保存真正的bool值,這不成問題.但是因?yàn)樗鼪]有,vector<bool>::operator[] (譯注:原文為()疑誤)不知如何返回一位的引用,并不存在這樣的東西. 為了解決它,vector<boo>::operator[]返回一個(gè)對(duì)象,其行為類似于位的引用,也稱為代理對(duì)象.(僅使用STL, 你并不需要明白什么是代理.它是一項(xiàng)值得了解的C++技術(shù).關(guān)于代理的信息,參考More Effective C++的Item30 還有Gamma等人(就是GoF)的設(shè)計(jì)模式一書中Proxy章節(jié)).深入本質(zhì)來(lái)看,vector<bool>可能類似于這樣: template <typename Allocator> vector<bool, Allocator> { public: class reference {...}; // class to generate proxies for // references to individual bits reference operator[](size_type n); // operator[] returns a proxy … } 現(xiàn)在,這些代碼不能編譯的原因就很明顯了. vector<bool> v; bool *pb = &v[0]; // error! the expression on tne right is // of type vector<bool>::reference*, // not bool* 因?yàn)樗荒芫幾g,所以vector<boo>不滿足STL容器的需要.vector<bool>在標(biāo)準(zhǔn)中,它也滿足了大多數(shù)STL容器的需要 ,但是它還不夠好.你寫的關(guān)STL容器的代碼越多,會(huì)越深刻地認(rèn)識(shí)到這一點(diǎn).當(dāng)一天來(lái)到時(shí),我保證,當(dāng)你會(huì)寫 出一個(gè)模板,它只在可以取得容器元素的地址時(shí)才工作.到那時(shí),你將突然明白容器和幾乎是一容器之間的區(qū)別. 也許你想知道為什么vector<bool>存在于標(biāo)準(zhǔn)中,而它并不是一個(gè)容器.答案是與一個(gè)貴族失敗的實(shí)驗(yàn)有關(guān).但讓我們 推遲一下討論,我有一個(gè)更緊迫的問題.如果vector<bool>應(yīng)避免,因?yàn)樗皇且粋€(gè)容器,那當(dāng)需要一個(gè)vector<bool>時(shí) 應(yīng)使用什么? 標(biāo)準(zhǔn)庫(kù)提供了兩個(gè)代替物,它們滿足幾乎所有需要.第一個(gè)是deque<bool>.deque提供幾乎所有vector提供的(唯一值得 注意的是reserve和capacity),并且deque<bool>是一個(gè)STL容器,它保存真正的bool值.當(dāng)然,deque底層的內(nèi)存不連續(xù). 所以不能傳遞deque<bool>中的數(shù)據(jù)給一個(gè)期望得到bool數(shù)組的C API(參見Item 16),但是vector<bool>也不能作這一點(diǎn) 因?yàn)闆]用可移植的方法取得vector<bool>中的數(shù)據(jù).(Item16中的技術(shù)不能在vector<boo>上編譯.因?yàn)檫@種技術(shù)依賴于 能夠取得容器元素的指針.我提到過vector<bool>中不保存bool值吧?) 第二個(gè)vector<bool>的代替物是bitset.bitset不是一個(gè)STL容器,但它是C++標(biāo)準(zhǔn)庫(kù)的一部分.與STL容器不同,它的大小 (元素總數(shù))在編譯期固定.因此,它不支持插入和刪除元素,近一步,因?yàn)樗皇且粋€(gè)STL容器,它也不支持iterator. 與vector<bool>類似,它使用一個(gè)壓縮的表示法,使得每個(gè)值只占用一位.它提供vector<bool>的特殊成員函數(shù),還包含 一系列操作位集(collection of bits)的特殊成員函數(shù).如果不在乎沒有迭代器和動(dòng)態(tài)大小,那么bitset也許正合你意. 現(xiàn)在我們來(lái)討論那個(gè)貴族的失敗的實(shí)驗(yàn),正是它將非STL容器的vector<bool>留在了標(biāo)準(zhǔn)庫(kù)中.我早先提到代碼對(duì)象在C++ 程序設(shè)計(jì)中十分有用.C++標(biāo)準(zhǔn)委員會(huì)的成員當(dāng)然也意識(shí)到了,他們決定開發(fā)vector<bool>做為一個(gè)演示.它說(shuō)明STL如何 支持包含通過代理訪問元素的容器.一但這個(gè)例子出現(xiàn)在標(biāo)準(zhǔn)中,而且它說(shuō)明得很詳細(xì),開發(fā)者將有一個(gè)參考,來(lái)實(shí)現(xiàn)自己 的基于代理的容器. 可是,最終他們發(fā)現(xiàn),不可能創(chuàng)建一種基于代理的容器,它滿足所有STL容器的需要.因?yàn)槟撤N原因,他們失敗了,而開發(fā)中 的這個(gè)例子留在了標(biāo)準(zhǔn)中.也許有人將探尋vector<bool>存在的原因,但現(xiàn)實(shí)地說(shuō),這不影響什么.重要的是:vector<bool> 不滿足STL容器的需要;你最好不要使用它;deque<bool>和bitset是基本能滿足你的需要vector<bool>代替品.
|