標準では、次の行で引数の評価順序を指定していません。
引数の評価順序は規定されていません。
何が
式の評価順序に制限がない場合、より優れたコードを生成できます
意味する?
たとえば、関数の引数を左から右に評価するようにすべてのコンパイラに要求することの欠点は何ですか? この未指定の仕様のために、コンパイラはどのような最適化を実行しますか?
標準では、次の行で引数の評価順序を指定していません。
引数の評価順序は規定されていません。
何が
式の評価順序に制限がない場合、より優れたコードを生成できます
意味する?
たとえば、関数の引数を左から右に評価するようにすべてのコンパイラに要求することの欠点は何ですか? この未指定の仕様のために、コンパイラはどのような最適化を実行しますか?
コンパイラがオペランドの評価を並べ替えることができるようにすると、最適化の余地が増えます。
これは、説明のために完全に構成された例です。
プロセッサが次のことができると仮定します。
ここで、次のような関数呼び出しがあるとします。
foo(a += 1, b += 2, c += 3, d *= 10);
OOEのないプロセッサでこれを左から右に実行する場合:
Cycle - Operation
0 - a += 1
1 - b += 2
2 - c += 3
3 - d *= 10
4 - d *= 10
5 - d *= 10
ここで、コンパイラがそれらを並べ替えることを許可した場合:(そして最初に乗算を開始します)
Cycle - Operation
0 - d *= 10
1 - a += 1, d *= 10
2 - b += 2, d *= 10
3 - c += 3
つまり、6サイクル対4サイクルです。
繰り返しますが、これは完全に考案されています。最近のプロセッサはそれよりもはるかに複雑です。しかし、あなたはその考えを理解します。
簡単な例を次に示します。次のような関数呼び出しがあるとします。
// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);
コンパイラは、p
2 回逆参照し (そして結果に基づいていくつかの計算を行い)、bar
1 回呼び出す必要があります。コンパイラが賢い場合、評価の順序を次のように変更する可能性があります。
int temp = *p * 3;
foo(temp, bar(), temp + 1);
そうすれば、「参照解除、3 倍」を 1 回だけ実行する必要があります。これは、一般的な部分式の削除として知られています。