C の i++ と ++i の間にパフォーマンスの違いはありますか?

エグゼクティブ サマリー:いいえ

i++ ++i より遅くなる可能性があります 、 i の古い値から 後で使用するために保存する必要があるかもしれませんが、実際には、最新のコンパイラはすべてこれを最適化します。

これは、この関数のコードを見ることで実証できます。両方とも ++ii++ .

$ cat i++.c
extern void g(int i);
void f()
{
    int i;

    for (i = 0; i < 100; i++)
        g(i);

}

++i を除いて、ファイルは同じです と i++ :

$ diff i++.c ++i.c
6c6
<     for (i = 0; i < 100; i++)
---
>     for (i = 0; i < 100; ++i)

それらをコンパイルし、生成されたアセンブラも取得します:

$ gcc -c i++.c ++i.c
$ gcc -S i++.c ++i.c

生成されたオブジェクトとアセンブラー ファイルの両方が同じであることがわかります。

$ md5 i++.s ++i.s
MD5 (i++.s) = 90f620dda862cd0205cd5db1f2c8c06e
MD5 (++i.s) = 90f620dda862cd0205cd5db1f2c8c06e

$ md5 *.o
MD5 (++i.o) = dd3ef1408d3a9e4287facccec53f7d22
MD5 (i++.o) = dd3ef1408d3a9e4287facccec53f7d22

Andrew Koenig 著「効率と意図」より :

そして:

したがって、結果の値が使用されない場合は、 ++i を使用します .しかし、より効率的だからではありません。それは私の意図を正しく述べているからです。


より良い答えは ++i です 場合によっては速くなりますが、遅くなることはありません。

誰もが i だと思っているようです int などの通常の組み込み型です .この場合、測定可能な違いはありません。

ただし、i の場合 が複雑なタイプの場合、測定可能な違いが見つかる可能性があります。 i++ の場合 インクリメントする前に、クラスのコピーを作成する必要があります。 ++it を使用しているため、コピーに含まれるものによっては実際に遅くなる可能性があります 最終値を返すだけです。

Foo Foo::operator++()
{
  Foo oldFoo = *this; // copy existing value - could be slow
  // yadda yadda, do increment
  return oldFoo;
}

もう 1 つの違いは、++i の場合です。 値の代わりに参照を返すオプションがあります。繰り返しますが、オブジェクトのコピーの作成に関係する内容によっては、これが遅くなる可能性があります。

これが発生する可能性がある実際の例は、反復子の使用です。イテレータのコピーがアプリケーションのボトルネックになる可能性は低いですが、 ++i を使用する習慣を身につけることは良い習慣です。 i++ の代わりに 結果が影響を受けない場所。