その場合の UB は [intro.execution]/15 に基づいています。
特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は順不同です。[...] 演算子のオペランドの値の計算は、演算子の結果の値の計算の前に並べられます。スカラー オブジェクトに対する副作用が、同じスカラー オブジェクトに対する別の副作用、または同じスカラー オブジェクトの値を使用した値の計算に対して順序付けされていない場合、動作は未定義です。
For ++(++i)
: [expr.pre.incr]/1 は++i
として定義されていi+=1
ます。これは [expr.ass]/1 につながります。
いずれの場合も、代入は、右オペランドと左オペランドの値の計算の後、代入式の値の計算の前に順序付けされます。
したがって、++(++i)
と同等(i+=1)+=1
の の場合、内側の代入は外側の代入の前に並べられ、UB はありません。
[intro.execution]/15 には UB の例があります。
i = i++ + 1; // the behavior is undefined
ここでのケースは少し異なります (ここで前置/後置の間違いを指摘してくれたOktalistに感謝します)。[expr.post.incr]/1 は、後置インクリメントの効果を記述します。それは述べています:
式の値の計算は++
、オペランド オブジェクトの変更の前に順序付けられます。
ただし、副作用(の変更)の順序付けに関する要件はありませんi
。このような要件は、代入式によって課されることもあります。ただし、代入式では、代入の前にオペランドの値の計算のみが必要です(副作用は必要ありません)。i = ..
したがって、とを介した 2 つの変更はシーケンス化i++
されておらず、未定義の動作が発生します。
NBには同じ問題i = (i = 1);
はありませんi = 1
。内部代入は、同じ式の値計算の前に順序付けされるという副作用を保証します。また、値は外部代入に必要です。これにより、それ (右側のオペランドの値の計算(i = 1)
) が外部代入の副作用の前に順序付けられることが保証されます。同様に、i = ++i + 1;
(と同等i = (i+=1) + 1;
) には動作が定義されています。
コンマ演算子は、副作用が順序付けられる例です。[expr.comma]/1
左の式に関連付けられたすべての値の計算と副作用は、右の式に関連付けられたすべての値の計算と副作用の前に並べられます。
[intro.execution]/15 には例i = 7, i++, i++;
(読み取り: ) が含まれており、これは(i=7), i++, i++;
定義済みの動作 ( become ) です。i
9