基于范围的for隐式地添加了' const '限定符
Range based for implicitly adds `const` qualifier?
让我们看看下面基于for循环的简单范围:
int a = 5, b = 6;
for (auto & i : {a, b})
{
std::cout << i << std::endl; // Works as expected.
i = 3; // Error!
}
gcc
抱怨assignment of read-only reference 'i'
,暗示与初始化列表一起使用的基于范围的for循环隐式地向引用添加了const
限定符,完全没有理由。
- 为什么会这样?
- 是否有一种工作方式允许修改基于循环的范围内的变量?
In
int a = 5, b = 6;
for (auto & i : {a, b})
您知道{a, b}
是两个元素a
和b
的std::initialiser_list
,其中a
和b
的值被复制。现在,std::initializer_list
只提供常量迭代器到它的元素,因为initializer_list
s是不可变的,所以你不能将值绑定到非const
左值引用。
一种选择是传递指针,这将使指针本身成为常量,而不是它们所指向的值:
for (auto& i : {&a, &b})
*i = 0;
现场演示
另一种选择是使用std::reference_wrapper
,但在这种情况下仍然需要调用.get()
或显式强制转换static_cast<int&>
:
for (auto& i : {std::ref(a), std::ref(b)})
i.get() = 0;
现场演示
考虑到std::reference_wrapper
具有到T&
的隐式转换操作符,如果在其他上下文中能够自动触发隐式转换(而不是调用.get()
),我不会感到惊讶。
还要注意,{a, b}
不是a
到b
的数字范围,它实际上只是这两个数字。因此,对于int a = 0, b = 10
,您将没有[0, 10]
,而是0
后面跟着10
的列表。
如果你想要一个"合适的"范围,我建议你看看Boost.Range.
这与基于范围的循环无关。问题是std::initializer_list<int>::iterator
是const int*
。您不能更改initializer_list
的内容。如果您要使用像std::vector<int>
这样的类型,这就可以了。
相关文章:
- 为什么"std::add_pointer"会添加之前删除的"const"?
- 为什么必须将 const 添加到 constexpr 中才能进行字符串文字声明?
- 为什么在函数参数前面添加 const 会出错?
- 在下面函数的返回中添加 const 限定符的重要性是什么?
- 超载 运算符添加const char
- 为什么重写方法并将 const 添加到参数类型有效
- 为什么不能在模板函数中向局部变量添加低级 const 类型
- 通过const Rerefence传递向量并将元素添加到向量
- 在qabstractItemmodel :: data()const中,如何添加一些线程安全数据
- 为什么 C 与 C++ 相反,禁止在指针到指针的两个级别添加 const 限定
- 将字符数组添加到 const string&in C++
- 为什么添加"const"可以解决"invalid operands to binary expression"
- 向指针添加"const"可以帮助优化吗?
- 在 for-each 循环中使用 'auto' 时是否需要添加'const'?
- 为什么const_cast(或static_cast)不添加const
- 向类添加const的正确方法
- 向size_t添加const会导致编译失败,这是标准行为吗
- 为什么添加"const"会使通用引用成为右值
- 'constexpr'非静态成员函数不会隐式'const'在 C++1y 中;添加'const'以避免行为更改
- 在合适的地方,在成员函数的末尾添加const是不是一个好习惯?