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 ループがそのように動作する理由がわかりません。もう 1 つの謎は、while ループが5for setを出力する理由です。sこれは、この数値が に挿入されていないためsです。

4

5 に答える 5

15

あなたのwhileループはループと同等ではありませんfor

ループはfor次と同等です

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

インクリメントはのに発生することに注意してくださいcoutwhileループでは、前にテストでインクリメントを行います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 述語が評価され、次に (述語が true の場合) 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 に答える