16-12 std::vector<bool>
在第O.1课——通过std::bitset实现位标志与位操作中,我们探讨了std::bitset如何将8个布尔值压缩至一个字节。这些位值可通过std::bitset的成员函数进行修改。
std::vector 还藏着一个有趣的诀窍:其 std::vector
面向高级读者的说明:
当模板类针对特定模板类型参数采用不同实现时,称为类模板特化class template specialization。本主题将在第26.4节——类模板特化中深入探讨。
与专为位操作设计的std::bitset不同,std::vector
使用 std::vector
在多数情况下,std::vector
#include <iostream>
#include <vector>
int main()
{
std::vector<bool> v { true, false, false, true, true };
for (int i : v)
std::cout << i << ' ';
std::cout << '\n';
// Change the Boolean value with index 4 to false
v[4] = false;
for (int i : v)
std::cout << i << ' ';
std::cout << '\n';
return 0;
}
在作者的64位机器上,这段代码输出:

std::vector 的权衡取舍
然而,std::vector
首先,std::vector
其次,其性能高度依赖具体实现(各实现甚至无需进行优化,更遑论优化质量)。据本文所述,高度优化的实现可显著快于其他方案,但优化不良的实现则会拖慢速度。
第三点也是最重要的一点:std::vector
尽管 std::vector
例如,当 T 为除 bool 以外的任何类型时,以下代码可正常运行:
template<typename T>
void foo( std::vector<T>& v )
{
T& first = v[0]; // get a reference to the first element
// Do something with first
}

避免使用 std::vector
现代共识认为应尽量避免使用 std::vector
遗憾的是,这种优化的 std::vector
我们的建议如下:
当满足以下条件时,请使用 (constexpr) std::bitset:
-
当所需位数在编译时已知、存储的布尔值数量不超过中等规模(例如低于64k),且有限的运算符和成员函数集(例如缺乏迭代器支持)能满足需求时,请使用(constexpr) std::bitset。
-
当需要一个可调整大小的布尔值容器且无需节省空间时,请优先选择 std::vector
。该类型行为与普通容器无异。 -
当需要动态位集进行位运算时,建议采用第三方实现的动态位集(如 boost::dynamic_bitset)。此类类型不会伪装成标准库容器,因为它们本身就不是。
最佳实践:
相较于 std::vector,优先选用 constexpr std::bitset、std::vector 或第三方动态位集实现。

浙公网安备 33010602011771号