考虑以下C ++ 11中的简单代码,取自C++ Primer, 5th Edition:
#include <iostream>
#include <string>
using std::cout;
using std::string;
using std::endl;
int main()
{
string s("Hello World!!!");
for (auto &c : s) // for every char in s (note: c is a reference)
c = toupper(c); // c is a reference, so the assignment changes the char
cout << s << endl;
return 0;
}
代码使用range for
循环迭代string
中的每个字符并将其更改为大写,这非常简单。让我感到困惑的是,引用c
似乎在运行时发生了变化。在本书的其他地方,作者提到引用而不是对象不能在运行时改变。任何人都可以了解编译器如何解释这段代码?
答案 0 :(得分:6)
你是对的,不能改变引用来引用不同的对象;它必须初始化为引用特定对象,并且在其整个生命周期内仍然是该对象的别名。
在这种情况下,参考不会改变;相反,为循环的每次迭代创建和销毁新的引用。这个范围风格的循环被定义为(或多或少)等效于旧式循环
for (auto it = s.begin(); it != s.end(); ++it) {
auto &c = *it;
// loop body
}
这样写的,很明显每次都有一个新的引用,而不是一个(以某种方式)更新的引用。
答案 1 :(得分:1)
对于for (auto &c : s)
的每次迭代,都会创建一个新的c
,在迭代结束时c
超出范围。
以下大致相当于:
for(int i = 0; i < s.length(); i++)
{
auto &c = *(s+i);
/*
Do Stuff;
*/
}
答案 2 :(得分:0)
引用内容的值随此代码而变化。但是在定义参考的整个范围内,即(带括号)
for (auto &c : s){ // for every char in s (note: c is a reference)
c = toupper(c);
}
引用指的是相同且唯一的变量。对于循环的每次迭代,您都会获得s
中下一个元素的新引用。
你无法做参考的内容确实改变了它所指的内容,即:
int i = 10;
int j = 20;
int& h = i;// j now refers to i
h = j; // modifies i, doesn't change what it refers to from i to j