vector-bool刺客

前言

1
2
std::vector<bool> BoolVec = { false, true, false, false };
bool& b = BoolVec[1]; // error: initial value of reference to non-const must be an lvalue

这怎么回事呢?

暂时没有实力来剖析原因,下文是对网络资料的摘抄,详见参考资料

std::vector is not a container

Not all of the templates defined in the C++ Standard Library that look like containers actually are containers. In particular, the standard library requires a specialization of vector for bool, and the specialization std::vector is NOT a container

std::vector<bool>是一个代理容器,也就是说它并不直接提供你它容纳的指针/引用,而是提供代理对象给你,你再通过代理对象间接访问。

Reason: optimization for space

sizeof(bool) >= 1, but Instead of storing a full char or int for every contained “bool”, it packs the bools and stores them as individual bits (inside, say, chars or ints) in its internal representation.

The things inside aren’t even standard bools. A standard bool is at least as big as a char, so that it can be used “normally.” So, in fact, vector does not even really store bools, despite the name.

后果:

  • 不能从[]或者迭代器获得bool&,而是一个看起来像,而且行为也像bool的代理对象vector<bool>::reference
  • 访问vector<bool>变慢,所以这是一种时间换空间的优化

参考资料