Range-for-loops和std :: vector <bool>

Val*_*tin 34 c++ for-loop range auto c++11

为什么这段代码有效

std::vector<int> intVector(10);
for(auto& i : intVector)
    std::cout << i;
Run Code Online (Sandbox Code Playgroud)

这不是吗?

std::vector<bool> boolVector(10);
for(auto& i : boolVector)
    std::cout << i;
Run Code Online (Sandbox Code Playgroud)

在后一种情况下,我收到一个错误

错误:从'std :: _ Bit_iterator :: reference {aka std :: _ Bit_reference}'类型的右值开始,无效初始化'std :: _ Bit_reference&'类型的非const引用

for(auto& i : boolVector)
Run Code Online (Sandbox Code Playgroud)

Que*_*tin 28

因为std::vector<bool>不是容器!

std::vector<T>迭代器通常取消引用a T&,你可以绑定到你自己的auto&.

std::vector<bool>但是,bool在整数内部将它们打包在一起,因此在访问它们时需要一个代理来执行位屏蔽.因此,它的迭代器返回一个Proxy.
并且因为返回的Proxy是prvalue(临时的),所以它不能绑定到左值引用,例如auto&.

解决方案:use auto&&,如果给定一个,将正确地折叠为左值引用,或者如果给定代理,则绑定并维护临时活动.

  • C++ 17解决方案(希望如此):只需使用[`for(i:boolVector)`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3853.htm) (5认同)
  • @ jingyu9575 [该提案被拒绝](http://stackoverflow.com/a/32706369/1708801)虽然gcc确实支持该功能一段时间. (5认同)
  • 代理实际上是一个prvalue. (4认同)
  • @John 是一个位于你正在访问的内容和你之间的东西。在这里,它可以在您这边的布尔值和存储方面的打包位之间进行转换。 (2认同)

Tob*_*ght 8

std::vector<bool> 不遵守标准的容器规则.

特别是,它operator[]不会返回bool&.

无效代码中的循环

#include <vector>
#include <iostream>

int main() {
  std::vector<bool> boolVector(10);
  for (auto& i: boolVector)
      std::cout << i;
}
Run Code Online (Sandbox Code Playgroud)

可以用三种方式重写,以迭代值:

  1. (只读)

    for (auto i: boolVector)
        std::cout << i;
    
    Run Code Online (Sandbox Code Playgroud)
  2. (只读,可能效率低下)

    for (auto const& i: boolVector)  
        std::cout << i;
    
    Run Code Online (Sandbox Code Playgroud)
  3. (读/写)

    for (auto&& i: boolVector)
        std::cout << i;
    
    Run Code Online (Sandbox Code Playgroud)

第一个和最后一个之间的选择取决于您是需要修改向量中的值,还是只是为了读取它们.


Sha*_*ger 6

vector<bool>(通常)专门用于将每个存储bool在一个位中,从而将存储成本从每个值一个字节减少到每八个值一个字节.没有我知道的处理器是位可寻址的,所以不可能存储对值中的值的引用vector<bool>.您需要使用plain auto,而不是auto&迭代值i.