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​​。