2012-03-23 11 views
2

これは奇妙な疑問のように思えるかもしれませんが、今日のC++プログラマについて怒っていた友人と話していました。代わりに、私は両方の方法を理解しますが、特定の理由があるC++でのイテレータの重要性

vector::iterator i; 
for(i = someVector.begin(); i!=someVector.end(); ++i){ 
    //Something here 
} 

より伝統的な理由秒の

for(int i = 0; i<((int) someVector.size()); ++i){ 
    //Something here 
} 

:彼は彼の主要なペットのpeeveは、このようなコードで反復の虐待、と述べました最初のものより優れていますか?それはパフォーマンスですか?それとも何か他の要因?

ありがとうございます。

+1

おかしい、私は最初のより伝統的な、あなたがCでそれを行う方法であると言うでしょう... –

+0

[この質問の複製](http://stackoverflow.com/questions/776624/whats) -faster-iterating-an-stl-vector-with-vectoriterator-with-at) – xdumaine

+4

リストやマップ、あるいはベクトルや配列以外のものについては、反復処理について考えてみてください。 – Pablo

答えて

3

どちらも優れたスタイルです。

最初は無駄で危険なキャストがあります。

2番目のコードでは、反復変数がループのスコープの外に漏れることが可能であり、等価テストは使用せず、イテレータでポストインクリメントを使用するため、無駄なコピーが作成されます。

ベターです:

using std::begin, std::end; 
for(auto it = begin(container), end_it = end(container); it != end_it; ++it) 

これは、任意のSTLコンテナ、配列、あなたがbeginendヘルパー機能を提供任意の容器で動作します。

+0

メンバー以外のbegin()およびend()関数の前にnamespace修飾子を付けることがわかります。これは引数依存の参照を禁止していますが、無料の機能として提供するユーティリティを削除しますか? – authchir

+0

@authchir:あなたがコメントする前に修正されました。 –

+0

@Niklas:私の答えで述べたように、これらは単純なol '配列で動作します。 –

1

vectorの場合、2つの間にはほとんど違いがありません。しかし、ランダムアクセスを全く持たないsetのようなデータ構造を反復する場合は、イテレータを使用する2番目のオプションが賢明な選択肢になります。

C++標準ライブラリは、多くの異なるタイプのコンテナでできるだけ一貫性のある "イテレータ"インターフェイスを作成するために大きな努力をしています。

+0

2番目のオプションは、イテレータに対して 'operator <'を必要とするため、ほとんどのコンテナでは動作しません。 –

+0

@BenVoigt:申し訳ありませんが、私はあなたのコメントを理解していません。どうぞお分かりですか? –

+0

@GregHewgill: '<'はRandome Iteratorsに対してのみ定義されています。すなわち、コンテナが 'std :: deque'または' std :: vector'だった場合にのみ動作します。したがって、より良いオプションは、すべてのイテレータタイプ。 –

0

一部のデータ構造では、サイズを計算するのが非効率的である場合があります。オプティマイザの処理量によっては、ループの繰り返しごとにsize()メソッドを呼び出すことになります。 2番目のコードを使うときは、サイズを計算するメソッドを呼び出すことに頼るのではなく、本当に目的が終わったかどうかを知ることだけです。

たとえば、リンクされたリストを考えてみましょう。リンクされたリストが内部的にカウントを保持するように設計されていない限り、リスト全体を繰り返してサイズを見つける必要があります。また、データ構造の場合、インデックスを使用して値を取得する方法はありません。この場合、適切なイテレータメソッドを使用する必要があります。

0

一般的に、イテレータを使用すると実際のパフォーマンスは向上しません。おそらく少ない。ただし、イテレータの "Cメソッド"よりもいくつかの利点があります。

1)イテレータを使用してコンテナを抽象化する方が簡単な場合があります。コンテナの型を変更し、インデックスの変更によって要素にアクセスする必要がある場合(あるいはランダムアクセスが不可能なために不可能な場合)、イテレータは退屈な編集を節約できます。

2)size()の反復を避けることができます。あなたはそれを一度計算することができますが、それを完全に避けることはなおさらです。

3)繰り返し処理しているコンテナの各要素へのポインタを処理します。これはより良い(よく、少なくとも私にとってはそうです)、恐らくインデックスよりもコンパクトです。

0

まず最初に、ほとんどのコードで明示的なループを使用しないでください。コレクションを操作する場合は、アルゴリズムを使用する必要があります。標準アルゴリズムの1つが仕事をしない場合は、通常、アルゴリズムとして必要なものを実装し、必要に応じてそのアルゴリズムを適用する必要があります(しかし注意を払うと、標準のアルゴリズムが機能します)。

あなたは本当に代わりに範囲ベースのループを使用することを検討して、明示的なループを記述する必要があります場合は、次の時間の

for (auto i : someVector) 
    // ... 

ほとんどは、しかし、これはアルゴリズムの実装にする必要があります。