2012-09-24 12 views
5

私はのためのループでそれを使用する必要がありますするにはどうすればよいイテレータまたはアクセス演算子でベクトルを反復すべきですか?

std::vector<int> MyVector; 
MyVector.push_back(5); 
MyVector.push_back(6); 
MyVector.push_back(7); 

としてベクトルを宣言していますか?

イテレータでiteratingすることで?

for (std::vector<int>::iterator it=MyVector.begin(); it!=MyVector.end(); ++it) 
{ 
    std::cout << "Vector element (*it): " << *it << std::endl; 
} 

またはそのアクセスイテレータによって、

for (std::vector<int>::size_type i=0; i<MyVector.size(); i++) 
{ 
    std::cout << "Vector element (i) : " << MyVector.at(i) << std::endl; 
} 

インターネットで見つかった例では、両方が使用されています。すべての条件の下でそれらの1つは他のものより優れていますか?そうでない場合は、どちらの方が優先されるべきですか?

+1

決定に名*「イテレータ」*助けになりませんか?ところで、 'std :: vector :: at'が何をするのか、あなたのコードでなぜそれを使うのかをはっきりと理解していただければと思います。 'std :: vector :: operator []'の代わりに 'std :: vector :: at'を使用すると、イテレータはおそらく常に高速になります(他の利点は無視してください)。 –

答えて

5

最初の形式は、それがより一般的で直感的であるように、標準ライブラリコンテナを反復処理のためのより一般的な形式です。コンテナを変更する必要がある場合、この反復コードは影響を受けません。すべての標準ライブラリコンテナタイプで動作するため、より汎用的なコードが提供されます。第二のフォーマットで

、境界用std::vector::at()チェックし、それが性能に少し有害であり得るので、それは、すべての反復で呼び出されるたび。このオーバーヘッドは、境界チェックが含まれていないため、最初の形式では存在しません。同じことがoperator[]を使用する場合も同様です。
パフォーマンスの遅れは、巨大なデータを操作している場合を除き、気づくほどではありません。

+0

Concur。ボトムライン:スキャンにはイテレータを使用し、ランダムアクセスにはイテレータを使用します。あなたはあなたがうれしいでしょう。 – WhozCraig

+0

@CraigNelsonいいえ、私はしません。私が範囲外のベクターにアクセスした場合、私には恥となりますが、毎回そのサイズをチェックさせません。デバッグモードでは、とにかく(VC++では)アサーションを取得します。 –

+0

@ChristianRauあなたがビジネスの範囲を知らずにシーケンスにランダムアクセスする場合は、@ChristianRauです。私はそれを事前に知ることを好む。しかし、あなたは大丈夫です。私は[]ではなく[]と言うことを意味していました。 touche。 – WhozCraig

3

std::vector's [] operatorを使用すると、forループ内でstd::vector::at()を使用すると、forループとstd :: vector :: at()の境界チェックでベクトルのサイズが2回確認されるためです。

最初のメソッドは他のコンテナでも使用できるため、コンテナのタイプを変更したときに役立ちます。

C++ 11を使用する場合は、範囲ベースのループを使用してください。あなたがC++ 11を持っている場合は、使用を

2

まず範囲ベース用:C++ 03で

for (auto i : MyVector) 
{ 
    std::cout << i; 
} 

またはBOOST_FOREACH

BOOST_FOREACH(int& i, MyVector) 
{ 
    std::cout << i; 
} 

またはstd::copy

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

手続きの質問として、at()は、インデックスが境界内にあることとスローをチェックしますそれ以外の場合は例外です。したがって、余分なチェックが必要な場合を除き、使用しないでください。あなたが持っている最初の方法は標準であり、うまくいきます。一部の人々は知識をひけらかすされているとさえ、それはそうのようにそれを書く:上記で

for (std::vector<int>::iterator it=MyVector.begin(), end = MyVector.end(); it!= end; ++it) 
{ 
    std::cout << "Vector element (*it): " << *it << std::endl; 
} 

私が代わりに各ループend()を呼び出すendイテレータをキャッシュされました。これが実際にパフォーマンスの違いをもたらすかどうかはわかりません。

1

には(あなたがほとんどない エラーから回復するために行う、本当にできる ものがある場合at()at()が唯一の適切な使用することを除いて)、「一方が他方より優れていない」があります。 イテレータとインデックスの使用は主にスタイルの1つで、メッセージはあなたが ということです。より慣用的なC++のやり方は、イテレータ ですが、他の背景(例えば、 数学者)からの人々は、より慣用的な索引付けを見つけるでしょう。

本当の違いがある場合があります。

  • イテレータのイディオムは、コンテナの他のタイプで動作しますが。この は、他の コンテナを実際に使用する可能性がある場合に関連します。

  • インデックス作成イディオムは、いくつかの異なる コンテナに対して単一のインデックスを使用できます。同一の サイズの複数のvectorを繰り返している場合は、インデックス化イディオムを使用すると、vectorのそれぞれに同じ要素 にアクセスしていることが明確になります。 (繰り返しますが、これは数学的な用途に 最も頻繁に発生するようです。)

  • 最後に、あなたが本当にランダムアクセスを行うこと、または何らかの方法で 要素を計算している任意の時間は、インデックスを使用すると、おそらく、より直感的です。 ( このような場合、あなたはおそらく唯一の が最後の瞬間にsize_tへの変換、intで計算をしたい。)

関連する問題