c++ - 基于范围的隐式添加 `const` 限定符?

标签 c++ c++11 constants initializer-list

让我们看看下面这个简单的基于范围的 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 限定引用,完全无端。

  1. 为什么会这样?
  2. 是否有一种变通方法允许在基于 for 循环的范围内修改变量?

最佳答案

int a = 5, b = 6;
for (auto & i : {a, b})

你有那个 {a, b}std::initialiser_list两个元素,ab ,其中 a 的值和 b被复制。现在,std::initializer_list only provides constant iterators to its elements , 因为 initializer_list s 是不可变的,因此您不能将值绑定(bind)到非 const左值引用。

一种选择是改为传递指针,这将使指针本身保持不变,而不是它们指向的值:

for (auto& i : {&a, &b}) 
    *i = 0;

Live demo

另一种选择是使用 std::reference_wrapper , 但这仍然需要调用 .get()或显式转换 static_cast<int&>在这种情况下:

for (auto& i : {std::ref(a), std::ref(b)}) 
    i.get() = 0;

Live demo

考虑到 std::reference_wrapper has an implicit conversion operator to T& ,如果在其他情况下您能够自动触发隐式转换(而不是调用 .get()),我不会感到惊讶。


另请注意 {a, b}不是 a 中的数字范围至b ,真的只是那两个数字。因此,int a = 0, b = 10你不会有 [0, 10]但是列表0紧随其后的是 10 .

如果您想拥有“适当”的范围,我建议您查看 Boost.Range .

关于c++ - 基于范围的隐式添加 `const` 限定符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31455648/

相关文章:

c++ - 无法反序列化 boost 图对象

c++ - .h 文件包含在头文件和 cpp 文件中

c++ - 构造函数初始化列表中的非成员初始化

c - 字符串文字与 const char[] 或 char[] 之间的区别

c++ - 如何通过 remove_cv 函数推断类型(const volatile int* vs const volatile int vs int * const volatile)

C++ 继承运算符未在派生类中调用

c++ - std::locale/std::facet 关键部分

c++ - `std::vector` 的快速哈希函数

c++ - 使用索引避免迭代器失效,保持干净的界面

javascript - Google Apps 脚本重新声明 Const 错误