C++ 中常规 "for" 语句和基于范围的 "for" 语句有什么区别

What is the difference between regular "for" statement and range-based "for" statement in C++

那么,这两种说法有什么区别:

for(auto i : VectorName){}


for(auto i = VectorName.begin(); i != VectorName.end(); i++){}

比如我有这个程序:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
 vector<char> vec = {'H','e','l','l','o','W','o','r','l','d','!'};
 for(auto i = vec.begin(); i != vec.end(); i++) // This loop has error
     {        
     cout << i << endl;
}
 for(auto k : vec) //This loop has no problem
 {
     cout << k << endl;
     }
     return 0;
}

我很困惑,因为在这个例子中 Microsoft docs:

// cl /EHsc /nologo /W4
#include <deque>
using namespace std;

int main()
{
    deque<double> dqDoubleData(10, 0.1);

    for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
    { /* ... */ }

    // prefer range-for loops with the following information in mind
    // (this applies to any range-for with auto, not just deque)

    for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
    { /* ... */ }

    for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
    { /* ... */ }

    for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
    { /* ... */ }
}

他们注意到语句的范围并不比常规范围好。

for (auto i = vec.begin(); i != vec.end(); i++)
{
    //cout << i << endl; // should be cout << *i << endl;
    auto& k = *i;
    cout << k << endl;
}

i 是一个迭代器,您必须推导它以检索几乎等于第二个代码段的值。

你的情况的不同之处在于,带有迭代器的第一个版本使用迭代器(这就是 cout << i << endl; 不起作用的原因),第二个版本(基于范围的 for 循环)给你副本、参考或常量参考。

所以这个:

for(auto i = vec.begin(); i != vec.end(); i++)
{
    cout << i << endl; // should be *i
}

使用迭代器(vec.begin() 为您提供第一个元素的迭代器)。

而这个:

for(auto i : vec)
{
    cout << i << endl;
}

使用向量中元素的副本。

同时:

for(auto& i : vec)
{
    cout << i << endl;
}

使用对矢量元素的引用。

常规 for 循环使用显式循环变量,在您的示例中是迭代器 iiter(很多时候它只是一个整数)。例如,要访问向量中的元素,您需要使用循环变量从向量中提取元素。

Range-based for loops 自动给你你循环的容器内的元素,所以不需要提取循环内的元素,你可以立即使用 k/elem .

关于您提到的评论:没有引用的特定基于范围的样式通常不利于性能(如果不需要复制)。

So, what is the difference between these two statement:

for(auto i : VectorName){}


for(auto i = VectorName.begin(); i != VectorName.end(); i++){}

第一个将遍历集合中的每个项; i 是项目的副本。

第二个给你更多控制范围; i 是一个迭代器,解引用访问项。