1

コンテナーを反復処理するこれら 2 つの方法の長所と短所は何ですか / どちらを好むか、またその理由は次のとおりです。

for (MyClass::iterator i = m.begin(), e = m.end() ; i != e ; i++)
{
    // ...
}

また

for (MyClass::iterator i = m.begin() ; i != m.end() ; i++)
{
    // ...
}

補助的な質問: i++ または ++i? なんで?

4

7 に答える 7

5

イテレータが自明でない (つまり、ポインタではない) 場合、++i は最適化されている場合とされていない場合がある一時へのコピーを含まないため、間違いなく高速です。

最初の形式は少し高速ですが、ループ内のものを消去または挿入すると間違っている可能性があります。

私が使用するコンテナの単純な反復のために

#define foreach BOOST_FOREACH // in some header

foreach(MyType &element, any_container) {
  // deal with element
}

ほとんどの場合、簡潔さと明快さのために。

于 2009-01-31T08:09:26.910 に答える
3

最適化をオフにしていない限り、どちらも同等です。i++ または ++i に関しては、++i は一時的な値を含まないため、より効率的です。

于 2009-01-31T07:47:02.090 に答える
2

通常の stl イテレータの場合、大きな違いはありませんが、コレクションが複雑で終了を要求するのが高価な場合は、終了を 1 回だけ要求する方が高速になる場合があります。

同様に、++i と i++ の場合、イテレータが (stl イテレータのような単なるポインタではなく) 複雑なクラスである場合、++i はより高価な操作になる可能性があります。前の状態のイテレータの。++i の場合、現在の状態でイテレータを返すため、それ自体への参照を返すことができます。

通常は、コードに問題があることをプロファイラーが特定した場合にのみ、コードを最適化するのが最善です。コードをできるだけ読みやすくしておくことをお勧めします。

于 2009-01-31T07:57:52.677 に答える
1

C++ の「コンテナー内のすべての要素に対して」ループは、コンテキストが反復ロジックを呼び出さない場合に最も効率的です。

for(Item& i : Container)
{
     dosomething(i);
}

また

for(const Item& i : Container)
{
     dosomething(i);
}
于 2016-11-18T21:26:57.810 に答える
1

実際には常に 2 番目のものを実行しますが、 end を複数回呼び出すと速度がまったく低下するのではないかと心配することがあります。これは最適化されるだろうという印象を受けましたが、確かなことはわかりません。

そして++i間違いなく。i++ よりも遅くなることはありません。どちらかといえば高速です。

于 2009-01-31T07:52:08.663 に答える
1

end()すべての反復で呼び出されるわけではないため、最初のものは高速です。いいえ、オプティマイザーはそれを簡単にキャッシュすることはできません。これは、この反復でコンテナーのサイズが変更されたかどうか (したがって、末尾が移動したかどうか) がわからないためです。これは、エイリアシングの問題により、const コンテナーにも適用されます。

i++i のコピーを返し、インクリメントします。++iインクリメントし、インクリメントされた値を返します。したがって、戻り値を破棄する場合は、++i必要な作業が少ない (コピーしない) ため、 を使用します。オプティマイザーはインラインi++呼び出しを修正する可能性が非常に高いため、同じくらい高速です++iが、それに依存しないでください。

自分?私が使う

for(int i = 0; i < m.size(); i++) {
    // ... do something with m[i]
}

それは最短で最も明確だからです。なぜintではないのMyClass::size_typeですか?それはよりシンプルであり、これまでエッジケースについて心配する必要がなかったからです. なぜi++ですか?基本型の場合、常に に最適化され++i、同僚にとって混乱が少ないためです。おまけiとして、数値としても使用できます。イテレータを使用すると、別のカウンターを保持するか、std::distance.

obecalplistは、これがやなどの標準コンテナの半分では機能しないことを指摘していmapます。実際、それらは適切なイテレータを使用する必要があります。iteratorこれに関連して、ジェネリック コードを記述するときは常に を使用する必要があります。

于 2009-01-31T07:54:00.343 に答える
0

Boost.Foreachは素晴らしい方法を導入しています。

#define foreach         BOOST_FOREACH
// ...
Container<Item> container;
// ...
foreach (Item item, container) {
  // do some stuff with the item
}
于 2009-01-31T08:16:16.977 に答える