for vs while 循环中的 C++ 迭代器行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12764499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:35:33  来源:igfitidea点击:

C++ iterator behaviour in for vs while loops

c++iterator

提问by Dan

I do not understand why iterating through a container with a for loop produces different results than iterating through it with a while loop. The following MWE illustrates this with a vector and a set of 5 integers.

我不明白为什么用 for 循环遍历容器会产生与用 while 循环遍历容器不同的结果。下面的 MWE 用一个向量和一组 5 个整数说明了这一点。

#include <iostream>
#include <vector>
#include <set>
using namespace std;

int main()
{
  vector<int> v;
  set<int> s;

  // add integers 0..5 to vector v and set s
  for (int i = 0; i < 5; i++) {
    v.push_back(i);
    s.insert(i);
  }

  cout << "Iterating through vector with for loop.\n";
  vector<int>::const_iterator itv;
  for (itv = v.begin(); itv != v.end(); itv++) cout << *itv << ' ';
  cout << '\n';

  cout << "Iterating through set with for loop.\n";
  set<int>::const_iterator its;
  for (its = s.begin(); its != s.end(); its++) cout << *its << ' ';
  cout << '\n';

  cout << "Iterating through vector with while loop.\n";
  itv = v.begin();
  while (itv++ != v.end()) cout << *itv << ' ';
  cout << '\n';

  cout << "Iterating through set with while loop.\n";
  its = s.begin();
  while (its++ != s.end()) cout << *its << ' ';
  cout << '\n';
}

The above produces:

以上产生:

Iterating through vector with for loop.
0 1 2 3 4 
Iterating through set with for loop.
0 1 2 3 4 
Iterating through vector with while loop.
1 2 3 4 0 
Iterating through set with while loop.
1 2 3 4 5 

The for loops work as expected but not the while loops. Since I'm using ++as a postfix, I don't understand why the while loops behave as they do. Another mystery is why the while loop prints a 5for set s, since this number was not inserted in s.

for 循环按预期工作,但不是 while 循环。因为我++用作后缀,所以我不明白为什么 while 循环会像它们那样运行。另一个谜是为什么 while 循环会打印一个5for set s,因为这个数字没有插入s.

回答by nneonneo

Your whileloop is not equivalent to the forloop.

您的while循环不等同于for循环。

The forloop is equivalent to

for循环相当于

itv = v.begin();
while(itv != v.end()) {
    cout << *itv << ' ';
    itv++;
}

Note that the increment happens afterthe cout. In your whileloops, you do the increment in the test, before cout. Even though you use postincrement, the increment takes effect before your loop body is executed.

需要注意的是增量发生cout。在您的while循环中,您在测试中进行增量,在cout. 即使您使用后增量,增量也会在执行循环体之前生效。

Write your whileloops like I did there and the discrepancy should disappear.

while像我在那里做的那样写你的循环,差异应该消失。

回答by Dietmar Kühl

When you iterate using the forloop you increment the iterator only after the body is evaluated. When you iterate using the whileloop you increment the iterator after the check but before the body of the loop. Dereferencing the iterator in the last iteration of your whileloops causes undefined behavior.

当您使用for循环进行迭代时,只有在对主体进行评估后才增加迭代器。当您使用while循环进行迭代时,您会在检查之后但在循环体之前增加迭代器。在while循环的最后一次迭代中取消引用迭代器会导致未定义的行为。

回答by Thomas Matthews

It could be because the compiler evaluates the its++in the while expression first before evaluating the rest of the expression.

这可能是因为编译器先评估its++while 表达式中的 ,然后再评估表达式的其余部分。

回答by Karoly Horvath

Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do.

由于我使用 ++ 作为后缀,我不明白为什么 while 循环会像它们那样运行。

That's because first the while predicate is evaluated, and then (if the predicate was true) the body of the while loop. By the time you try to access the value in the body, the iterator was already incremented.

这是因为首先对 while 谓词求值,然后(如果谓词为真)再对 while 循环体求值。当您尝试访问正文中的值时,迭代器已经递增。

回答by sehe

Just a few 'random' style hints, mainly showing algorithm use and modern C++11 features.

只是一些“随机”样式提示,主要显示算法使用和现代 C++11 功能。

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>

int main()
{
    const std::vector<int> v { 0,1,2,3,4 };
    const std::set<int>    s { 0,1,2,3,4 };

    for (auto element : v)
        std::cout << element << ' ';
    std::cout << '\n';

    for (auto element : s)
        std::cout << element << ' ';
    std::cout << '\n';

    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';

    std::copy(s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}