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。