vectorbool 這麼多規則的異常

標準(第 23.3.7 節)規定提供 vector<bool> 的特化,它通過打包 bool 值來優化空間,因此每個僅佔用一位。由於在 C++中不能對位進行定址,這意味著對 vector 的幾個要求沒有放在 vector<bool> 上:

  • 儲存的資料不需要是連續的,因此 vector<bool> 不能傳遞給期望 bool 陣列的 C API。
  • at()operator [] 和迭代器的解引用不會返回對 bool 的引用。相反,他們通過過載其賦值運算子返回一個代理物件(不完美地)模擬對 bool 的引用。例如,以下程式碼可能對 std::vector<bool> 無效,因為解除引用迭代器不會返回引用:

Version >= C++ 11

std::vector<bool> v = {true, false};
for (auto &b: v) { } // error

類似地,期望 bool& 引數的函式不能與 operator []at() 應用於 vector<bool> 的結果一起使用,或者使用解除引用其迭代器的結果:

  void f(bool& b);
  f(v[0]);             // error
  f(*v.begin());       // error

std::vector<bool> 的實現取決於編譯器和體系結構。通過將 n 布林值打包到記憶體的最低可定址部分來實現專業化。這裡,n 是最低可定址儲存器的位大小。在大多數現代系統中,這是 1 位元組或 8 位。這意味著一個位元組可以儲存 8 個布林值。這是對傳統實現的改進,其中 1 個布林值儲存在 1 位元組的儲存器中。

注意: 下面的示例顯示了傳統與優化的 vector<bool> 中單個位元組的可能按位值。這並不總是適用於所有架構。然而,它是視覺化優化的好方法。在下面的例子中,一個位元組表示為[x,x,x,x,x,x,x,x]。

傳統的 std::vector<char> 儲存 8 個布林值:

Version >= C++ 11

std::vector<char> trad_vect = {true, false, false, false, true, false, true, true};

按位表示:

[0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,1]

專門的 std::vector<bool> 儲存 8 個布林值:

Version >= C++ 11

std::vector<bool> optimized_vect = {true, false, false, false, true, false, true, true};

按位表示:

[1,0,0,0,1,0,1,1]

請注意,在上面的示例中,在傳統版本的 std::vector<bool> 中,8 個布林值佔用 8 個位元組的記憶體,而在優化版本的 std::vector<bool> 中,它們僅使用 1 個位元組的記憶體。這是對記憶體使用的重大改進。如果你需要將 vector<bool> 傳遞給 C 風格的 API,則可能需要將值複製到陣列中,或者如果記憶體和效能存在風險,則可以找到更好的方法來使用 API​​。