Skip to content

败犬日报 2024-11-07

1. std::vector<bool> 的坑

因为 std::vector<bool> 是 vector 的特化,尝试通过位压缩来优化存储空间,8 个 bool 压成一个字节。

众所周知内存每个地址都是一字节,bool 数组的每个 bool 地址互不相同。但是 vector<bool> 一个字节是怎么区分 8 个地址呢?做不到。所以 std::vector<bool> 使用了代理对象(proxy object)让它使用上接近 vector。

比如访问元素 v[x] 会得到一个代理对象,而不是一个直接的 bool 引用。

cpp
std::vector<bool> vec = {true, false, true};
bool& ref = vec[0];  // 编译错误:不能将代理对象赋值给 bool&

当模板和 vector 结合时可能更难注意到这个坑:

cpp
template <typename T>
void f() {
    std::vector<T> a(10);
    T& x = a[0];
}
f<bool>();

规避的话可以 std::vector<uint8_t>std::vector<char> 实现相同功能。

标准委员会为了推销他们的特化,证明特化是多有用的一个特性的产物。结果就成了这样。

https://en.cppreference.com/w/cpp/container/vector_bool


目前编译器没有提供检查 vector<bool> 的功能。

https://reviews.llvm.org/D29118 有人做过,但是因为这个实现检查不了模板实例化时产生 vector<bool> 所以没合。

2. 设计模式其实就是一些套路

用的人多了,就成了典。

很喜欢老工程壬的一句话,设计模式就是给语言打补丁。