Range-for-loops and std::vector<bool>
为什么这个代码有效
1 2 3
| std::vector<int> intVector(10);
for(auto& i : intVector)
std::cout << i; |
但事实并非如此?
1 2 3
| std::vector<bool> boolVector(10);
for(auto& i : boolVector)
std::cout << i; |
在后一种情况下,我会得到一个错误
error: invalid initialization of non-const reference of type ‘std::_Bit_reference&’ from an rvalue of type ‘std::_Bit_iterator::reference {aka std::_Bit_reference}’
1
| for(auto& i : boolVector) |
- 使用C++ 11的范围正确的方法可能是什么?(搜索"vector")
因为std::vector不是一个容器!
std::vector的迭代器通常取消对T&的引用,可以将其绑定到自己的auto&上。
但是,std::vector将其bool打包在整数内,因此访问它们时需要代理来进行位屏蔽。因此,它的迭代器返回一个Proxy。由于返回的Proxy是一个prvalue(临时的),它不能绑定到一个lvalue引用,如auto&。
解决方案:使用auto&&,如果给定值,它将正确地折叠为左值引用;如果给定代理,则绑定并保持临时活动。
- 代理实际上是一个prvalue。
- C++ 17解决方案(希望):只使用EDOCX1,0
- @Jingyu9575虽然GCC有一段时间支持这一功能,但该提议被拒绝。
- 在这种情况下,解决方案是使用auto const,因为代码不需要通过代理进行写入。
- @谢谢你!我不再回顾我的价值类别:p
std::vector不遵守标准集装箱规则。
特别是它的operator[]没有返回bool&。
无效代码中的循环
1 2 3 4 5 6 7 8
| #include <vector>
#include <iostream>
int main() {
std::vector<bool> boolVector(10);
for (auto& i: boolVector)
std::cout << i;
} |
可以通过以下三种方法中的任意一种重写值:
(只读)
1 2
| for (auto i: boolVector)
std::cout << i; |
(只读,可能效率低下)
1 2
| for (auto const& i: boolVector)
std::cout << i; |
(读/写)
1 2
| for (auto&& i: boolVector)
std::cout << i; |
在第一个和最后一个之间的选择取决于您是需要修改向量中的值,还是仅仅为了读取它们。
- for(auto i :boolVector)似乎可以修改值。我的示例实现依赖吗?另外,您能详细说明一下为什么for(auto const& i : boolVector)效率低下吗?
- 只是因为这是不必要的间接性。任何合适的优化器都将创建相同的代码,因此"可能"。
- 如果我理解正确,这适用于任何类型的参考,这意味着for(auto &&i : boolVector)也有同样的问题,是吗?
- 你的链接对我不起作用(它是隐藏在一些基于javascript或cookie的垃圾中吗?),但是的,auto i将绑定到boolVector迭代器的取消引用类型,即std::vector::reference。它可能会在分配给时修改基础集合。bool的矢量总是令人惊讶的!
vector通常专门用于将每个bool存储在一个位中,从而将存储成本从每值一个字节减少到每8个值一个字节。目前我所知道的任何处理器都不是位可寻址的,因此不可能存储对vector中值的引用。迭代值i需要使用plain auto,而不是auto&。