++i
一部のプログラマーが書く代わりに通常の for ループを書く理由はありi++
ますか?
9 に答える
++i
そのセマンティクスにより、わずかに効率的です。
++i; // Fetch i, increment it, and return it
i++; // Fetch i, copy it, increment i, return copy
int のようなインデックスの場合、効率の向上は最小限です (存在する場合)。イテレータやその他のより重いオブジェクトの場合、そのコピーを避けることは真の勝利になる可能性があります (特に、ループ本体に多くの作業が含まれていない場合)。
例として、任意精度の整数を提供する理論上の BigInteger クラスを使用する次のループを考えてみましょう (したがって、ある種のベクトルのような内部構造)。
std::vector<BigInteger> vec;
for (BigInteger i = 0; i < 99999999L; i++) {
vec.push_back(i);
}
その i++ 操作には、基本的にインデックス オブジェクトのもう 1 つのコピーを作成する以上のことを行わないループのコピー構築 (つまり、演算子 new、桁ごとのコピー) と破棄 (演算子 delete) が含まれます。基本的に、接頭辞で十分だったはずの接尾辞のインクリメントを使用するだけで、実行する作業が2倍になりました(そしてメモリの断片化が増加した可能性が最も高いです)。
整数の場合、プリインクリメントとポストインクリメントに違いはありません。
i
が重要なクラスのオブジェクトである場合は、++i
オブジェクトが変更されてから評価されるため、通常は好まれますが、i++
評価後に変更されるため、コピーを作成する必要があります。
++i
プレインクリメントです。i++
ポストインクリメントです。
ポストインクリメントの欠点は、余分な値が生成されることです。変更中に古い値のコピーを返しますi
。したがって、可能な場合は避ける必要があります。
整数では、それが優先されます。
ループ変数がクラス/オブジェクトである場合、違いが生じる可能性があります (有意な違いかどうかは、プロファイリングによってのみわかります)。これは、インクリメント後のバージョンでは、破棄されるオブジェクトのコピーを作成する必要があるためです。
そのコピーの作成が高価な操作である場合、ループを通過するたびにその費用を支払うことになります。理由はまったくありません。
常に in for ループを使用する習慣を身に++i
つければ、この特定の状況で行っていることが理にかなっているかどうかを立ち止まって考える必要はありません。あなたはいつもそうです。
ソルトでその重みに見合うコンパイラはありません。
for(int i=0; i<10; i++)
と
for(int i=0;i<10;++i)
++i と i++のコストは同じです。唯一の違いは、++i の戻り値が i+1 であるのに対し、i++ の戻り値は i であることです。
したがって、++i を好む人にとっては、おそらく正当な理由はなく、個人的な好みにすぎません。
編集:他のすべての投稿で述べられているように、これはクラスにとって間違っています。i がクラスの場合、i++ はコピーを生成します。
これには理由があります: パフォーマンスです。i++ はコピーを生成しますが、すぐに破棄するのはもったいないことです。確かに、コンパイラは、プリミティブの場合はこのコピーを最適化できますi
が、そうでない場合はできません。この質問を参照してください。
他の人がすでに述べたように、ユーザー定義型の場合、通常、プリインクリメントはポストインクリメントよりも高速です。これがなぜそうなのかを理解するには、両方の演算子を実装するための一般的なコードパターンを見てください。
Foo& operator++()
{
some_member.increase();
return *this;
}
Foo operator++(int dummy_parameter_indicating_postfix)
{
Foo copy(*this);
++(*this);
return copy;
}
ご覧のとおり、プレフィックスバージョンは単にオブジェクトを変更し、参照によってオブジェクトを返します。
一方、postfixバージョンは、実際のインクリメントが実行される前にコピーを作成する必要があり、その後、そのコピーが値によって呼び出し元にコピーされます。ソースコードから明らかなように、postfixバージョンにはプレフィックスバージョンへの呼び出しが含まれているため、より多くの作業を行う必要があります。++(*this);
組み込み型の場合、値を破棄する限り、つまり、またはなどのより大きな式に埋め込ま++i
ない限り、違いはありません。i++
a = ++i
b = i++
postfix を使用すると、メモリ内のより多くのオブジェクトでインスタンス化されます。for ループで接尾辞演算子を使用した方がよいという人もいます。
個人の好み。
いつもの。時々それは重要ですが、ここでジャークのように見えることはありませんが、尋ねなければならない場合は、おそらくそうではありません.