3

我不明白为什么使用 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';
}

以上产生:

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 

for 循环按预期工作,但 while 循环不按预期工作。由于我将++其用作后缀,因此我不明白为什么 while 循环的行为如此。另一个谜团是为什么 while 循环会打印一个5for 集合s,因为这个数字没有插入s

4

5 回答 5

15

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

循环for相当于

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

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

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

于 2012-10-06T22:41:07.663 回答
12

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

于 2012-10-06T22:41:57.230 回答
2

这可能是因为编译器its++在评估表达式的其余部分之前首先评估了 while 表达式中的值。

于 2012-10-06T22:41:04.703 回答
1

因为我使用 ++ 作为后缀,所以我不明白为什么 while 循环的行为如此。

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

于 2012-10-06T22:41:21.410 回答
1

只是一些“随机”风格的提示,主要展示算法使用和现代 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';
}
于 2012-10-06T23:03:15.607 回答