使用C ++ 11 Range for循环更改字符串中的字符

时间:2013-06-26 13:41:47

标签: c++ for-loop c++11 reference

我读了C++ Primer

  

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

此外,他们给出了这段代码:

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); 

3 个答案:

答案 0 :(得分:5)

现有变量没有重新绑定,在每次迭代时,“旧”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循环的圆括号内声明的变量将循环体作为其范围。

答案 1 :(得分:4)

否。for循环中为每次迭代初始化一个新引用。

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

相当于:

for (auto it = s.begin(); it != s.end(); ++it)
{
    auto &c = *it;
    c = toupper(c);
}

答案 2 :(得分: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循环在每次迭代时进入并离开范围。