为什么在for循环中引用常量可以被重新分配?

30

我是C++的新手,对以下内容感到困惑:

vector<int> v = { 1,2 };
const int &r1 = v[0];
//r1 = v[1];  // compiler will show error.

我知道引用常量r1不能被重新赋值。但是请看下面的代码:

for (const int &r2 : v) cout << r2;

为什么那不会出错?常量引用 r2 被赋值了两次,对吗?


它被分配给v[0],然后是v[1],不是吗? - Xun Chenlong
6
为什么允许使用for(int k = 0; k < 2; k++) {const int &r1 = v[k];}这段代码? - user253751
2
@immibis 我读到这个就像读一个公案一样,感觉茅塞顿开 :) - Numeri
3个回答

35

不,它没有被分配两次。r2存在于迭代的开始(循环体的单个轮回)直到迭代结束。下一次迭代中的r2是另一个同名对象。每次迭代都有自己的r2,并且它们各自被单独初始化。


但是 r2 是一个常量。我读的书说 r2 是一个低级别的常量,其值不能被改变。我的理解正确吗? - Xun Chenlong
@XunChenlong 请在评论之前仔细阅读答案。答案已经回应了您的评论。 :) - user743382
7
哦,我明白了。一个迭代指的是一个循环。我把它误认为整个for语句了。这有所帮助。抱歉我的英文不好,谢谢! - Xun Chenlong

24
根据C++11标准[stmt.ranged]的规定:
for (const int &r2 : v) std::cout << r2;

其中 ¹v 是一个向量,等价于:

{
    auto && __range = (v);
    for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin)
    {
        const int &r2 = *__begin; // <-- new variable in each iteration
        std::cout << r2;
    }
}

演示

参考常量r2被分配了两次,对吗?

不是的。每次迭代都会有一个新的r2变量。


¹ 基于范围的for循环也可以用于其他类型的集合,包括原始数组。这里给出的等价性是std::vector的通用等价性。


6

基于范围的 for 如下所示:

attr(可选)for( range_declaration : range_expression )loop_statement

其中 range_declaration

range_declaration - 命名变量的声明,其类型为 range_expression 所表示的序列元素的类型,或者是该类型的引用。通常使用自动推导的 auto 限定符。

因此,在每次迭代中都会引入新的声明,该引用仅存在于下一次循环迭代之前。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接