プログラミングの授業で、教授はx++
とについて教えてくれ++x
ました。x は整数です。
彼は、シナリオでは、 または のいずれかを配置することができx++
、++x
より++x
効率的であると述べました (少しずつではありますが、それでも理論的にはより効率的です)。
しかし、私は理由を忘れました。誰でも知っていますか?これはJavaでした。
プログラミングの授業で、教授はx++
とについて教えてくれ++x
ました。x は整数です。
彼は、シナリオでは、 または のいずれかを配置することができx++
、++x
より++x
効率的であると述べました (少しずつではありますが、それでも理論的にはより効率的です)。
しかし、私は理由を忘れました。誰でも知っていますか?これはJavaでした。
Javaでは効率的ではありません。インクリメント/デクリメント演算子をオーバーロードできる言語ではより効率的ですが、それ以外のパフォーマンスはまったく同じです。
x++
との違いは++x
、 インクリメントされる前x++
の値を返し、インクリメントされた後の値を返すことです。コード生成に関しては、少なくともどちらかを互換的に使用できる場合は、どちらもまったく同じ数の命令を補います (互換的に使用できない場合は、どちらが高速かを気にする必要はありません。必要なものを選択してください)。唯一の違いは、インクリメント命令が配置される場所です。x
++x
x
C++ では、クラスは前置 ( ) 演算子++x
と後置 ( x++
) 演算子の両方をオーバーロードできます。それらをオーバーロードする型を扱う場合、ほとんど例外なく前置演算子を使用する方が高速です。これは、後置演算子のセマンティクスにより、使用しない場合でもインクリメント前のオブジェクトのコピーが返されるためです。前置演算子は、変更されたオブジェクトへの参照を単純に返すことができます (そして、C++ 開発者がコピーではなく参照を返すことを好むことを神は知っています)。これは、C++よりも優れていると考える理由になる可能性があります。C++を使用する習慣を 身につければ、C++ に切り替えた場合のわずかなパフォーマンスの問題を回避できます。ただし、Java のみのコンテキストでは、どちらも完全に同等です。++x
x++
++x
上記のコメントのpstと同じように、私はx++
orの戻り値を決して使用し++x
ません。
好奇心から、生成されたバイトコードを確認できます。
このプログラム:
public static void main(String args[]) {
int i = 1; //bytecode 0, 1
i++; //bytecode 2
++i; //bytecode 5
int a = ++i; //bytecode 8, 11, 12
int b = i++; //bytecode 13, 14, 17
}
次のバイトコードを生成します。
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iinc 1, 1
5: iinc 1, 1
8: iinc 1, 1
11: iload_1
12: istore_2
13: iload_1
14: iinc 1, 1
17: istore_3
18: return
したがって、修正前と修正後の演算子は、バイトコードの観点からは厳密に同一であることがわかります(操作の順序は別として)。
JITがコードのその部分をコンパイルする場合、すべての賭けは無効になります。たとえば、上記のコードは、副作用がないため、そのままコンパイルできます。
実のところ、PDP-11やおそらく VAXのC*x++
よりも高速でした。これは、単一の命令 (自動インクリメント レジスタの遅延) にコンパイルされたためです。同様に よりも高速でした。逆参照なしでどちらの形式を使用しても、コンパイラがその命令を生成した場合、逆参照が発生したままになるため、無駄な命令が生成された場合にのみ高速になります。*++x
*--x
*x--
そんな日々はとうの昔に過ぎ去りました。