2

我在C++ Primer中读到:

如果我们想更改字符串中字符的值,我们必须将循环变量定义为引用类型(第 2.3.1 节,第 50 页)。请记住,引用只是给定对象的另一个名称。当我们使用引用作为控制变量时,该变量依次绑定到序列中的每个元素。使用引用,我们可以更改引用绑定到的字符。

他们进一步给出了这个代码:

string s("Hello World!!!");
// convert s to uppercase
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
in s
cout << s << endl;

这段代码的输出是 HELLO WORLD!!!

我还读到:

无法重新绑定引用以引用不同的对象。因为无法重新绑定引用,所以必须初始化引用。

问题:每次引用变量c绑定到字符串 s 的下一个字符时,这段代码不会导致重新绑定吗?

for (auto &c : s)   
    c = toupper(c); 
4

3 回答 3

6

没有重新绑定现有变量,在每次迭代中,“旧”c 死掉,“新”c 再次创建,初始化为下一个字符。该for循环相当于:

{
    auto it = begin(s);
    auto e = end(s);
    // until C++17: auto it = begin(s), e = end(s);
    for(; it!=e; ++it) {
        auto &c = *it;
        c=toupper((unsigned char)c);
    }
}

您会看到,在每次迭代中,c都会重新创建和重新初始化。

换句话说,在基于范围的for循环的圆括号内声明的变量将循环体作为其范围。

于 2013-06-26T13:43:18.110 回答
4

不会。循环中的每次迭代都会初始化一个新的引用for

for (auto &c : s)   
    c = toupper(c); 

相当于:

for (auto it = s.begin(); it != s.end(); ++it)
{
    auto &c = *it;
    c = toupper(c);
}
于 2013-06-26T13:43:44.770 回答
1

考虑

char s[5] = {'h','e','l','l','o'};

for (int secret_index=0; secret_index<5; ++secret_index) {
    char &c = s[secret_index];
    c = toupper(c);
}

每次迭代都会初始化一个新的引用(具有相同的变量名)。也就是说,for 循环在每次迭代时进入和离开范围。

于 2013-06-26T13:47:25.080 回答