イテレータを使用してstd :: vectorをループするプログラムを作成しています。 forステートメントで++ itを実行すると、コードがより効率的になると誰かが教えてくれました。言い換えれば、彼らはそれを言っています:
for ( vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); ++it )
より速く走る
for ( vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); it++ )
これは本当ですか?もしそうなら、効率改善の背後にある理由は何ですか? it ++/++ itが行うのは、イテレータをベクトル内の次の項目に移動することだけですよね。
プレインクリメントが高速である理由は、ポストインクリメントが戻るために古い値のコピーを作成する必要があるためです。 GotW#2 のように、「ポストインクリメントの場合、オブジェクトはそれ自体をインクリメントしてから、古い値を含む一時オブジェクトを返す必要があるため、プリインクリメントはポストインクリメントよりも効率的です。これは、intなどのビルトインにも当てはまります。 。」
GotW#55 正規形式のポストインクリメントを提供します。これは、プレインクリメントに加えていくつかの作業を行う必要があることを示しています。
T T::operator++(int)
{
T old( *this ); // remember our original value
++*this; // always implement postincrement
// in terms of preincrement
return old; // return our original value
}
他の人が指摘しているように、コンパイラによってはこれを最適化することも可能ですが、戻り値を使用しない場合は、この最適化に依存しないことをお勧めします。また、C++ではプリインクリメントを使用するのが良い習慣だと思いますが、コピーコンストラクターが簡単なタイプの場合、パフォーマンスの違いは非常に小さい可能性があります。
ベクトルに違いが生じる可能性はほとんどありません。
一般に、++it
がit++
より遅くなる可能性は非常に低く(オーバーロードされている場合、適切な実装を想定)、ただ速くなる可能性があります。その理由は、イテレータクラス自体がまったく複雑な場合、it++
はit
がインクリメントされる前に値を返さなければならないため、実装は通常コピーを作成するためです。
ベクトルイテレータはおそらく「単なるポインタ」であり(最適化された非デバッグビルドの場合)、両方のoperator++
がインライン化されます。戻り値は未使用であるため、通常、コピーは省略されます。したがって、違いはありません。私は++it
と入力する習慣があります。理由は次のとおりです。
1)あるイテレータタイプでは、いつか違いが生じる可能性があり、そのタイプのために特別なことをする必要はありません。
2)個人的には、プレフィックス演算子は、「使用してからインクリメントする」のではなく、「インクリメントする」という意図をより明確に表現していると思います。
it++
は次の操作を実行します。
it
のコピーを作成しますit
it
を返します++it
は次の操作を実行します。
it
it
を返しますなぜならit++
コピーを作成します。「遅い」と言えます。ただし、適切なコンパイラは、ほとんどの定義済みタイプに対してこの違いを最適化します。一部のユーザー定義タイプでは、can高速です。
時々そうです。いくつかでは、それは離れて最適化され、同じになります。 std :: vector <>(および他のstd-iterators)の場合、同じになるように最適化される可能性があります。
はい++オブジェクトのコピーを返し、それ自体をインクリメントする必要があるため、より効率的です。
It ++が一時的なコピーを作成する可能性があります。
また、C++では、誰かがポストインクリメント演算子をオーバーロードした可能性があります。
これらは両方とも、パフォーマンスを低下させる可能性があります。どちらも実際には問題にならない可能性があります。特に、一時コピーは、Forループの3番目の式に副作用がないため、ほとんどのコンパイラーによって最適化されます。
はい。私が覚えている限り、++ it ++は一時オブジェクトを作成するのに対し、++ it ++は作成しないため、++よりも効率的です。