C ++ 11標準のn3290ドラフト(実際の標準テキストにできるだけ近い)を読んでいますが、i = i++ + 1;
未定義の動作が発生することに気づきました。私は以前に同様の質問を見たことがありますが、それらは古い基準(シーケンスポイント)の観点から回答されました。新しい標準では、代わりに、式と部分式の実行の間の関係の前後の順序付けの概念が導入されています。
1.9 13前にシーケンスされたのは、単一のスレッド(1.10)によって実行される評価間の非対称で推移的なペアワイズ関係であり、これらの評価の間に半順序が生じます。AとBの2つの評価が与えられた場合、AがBの前にシーケンスされている場合、Aの実行はBの実行に先行します。AがBの前にシーケンスされておらず、BがAの前にシーケンスされていない場合、AとBはシーケンスされていません。[注:順序付けられていない評価の実行は重複する可能性があります。—end note]評価AとBは、AがBの前にシーケンスされるか、BがAの前にシーケンスされる場合、不確定にシーケンスされますが、どちらが指定されていません。[注:不確定に順序付けられた評価は重複できませんが、どちらかが最初に実行される可能性があります。—エンドノート]
1.9 14完全式に関連するすべての値の計算と副作用は、評価される次の完全な式に関連するすべての値の計算と副作用の前に順序付けられます。
1.9 15特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は順序付けられていません。[注:プログラムの実行中に複数回評価される式では、その部分式のシーケンスされていない評価とシーケンスが不確定な評価を、異なる評価で一貫して実行する必要はありません。—end note]演算子のオペランドの値の計算は、演算子の結果の値の計算の前に順序付けられます。スカラーオブジェクトの副作用が、同じスカラーオブジェクトの別の副作用、または同じスカラーオブジェクトの値を使用した値の計算に比べて順序付けされていない場合、動作は定義されていません。
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
私がそれを理解する方法では、それは次のように機能します:
operator=
2つのオペランド式があります。i
とを参照しi++ + 1
ます。どちらも互いにシーケンスされていません。2つ目はに副作用がありますi
が、1つ目は副作用がないか、値の計算に使用されていないようです(または、「同じスカラーオブジェクトの値を使用した値の計算」を参照していますか?実際には依存していますか? iに格納されている値?そうは思わない)、したがって、未定義の動作ではありません。operator=
実行は、両方のオペランド評価の後にシーケンスされます。に副作用がi
ありますが、両方のオペランドを参照して適切に順序付けられているため、未定義の動作ではありません。i++ + 1
明らかに定義された動作です。
私はここで何かについて間違っていますか?それとも、この行は他の理由で未定義の動作ですか?
PS。標準は実際に言う
演算子のオペランドの値の計算は、演算子の結果の値の計算の前に順序付けられます。
、そしてそれはこの文脈での副作用についてはまったく言及していません。ただし、シーケンス関係は、式の評価と、評価=値の計算+副作用の間でのみ定義されます。したがって、このドラフトはここでは矛盾していると想定するか、この行では値の計算ではなく評価を意味していると想定する必要があります。それとも私はここで間違っていますか?
編集:
私はここで自分自身に答えると思いますが、それが私の混乱の理由でした:
5 1式は、計算を指定する一連の演算子とオペランドです。式は値になり、副作用を引き起こす可能性があります。
したがって、演算子のオペランド自体は部分式ではありません。したがって、全体の値の計算のみi = i++ + 1;
がシーケンスされ、副作用のシーケンスについては標準で言及されていません。それが未定義の理由です。
たとえば、operator=
与えられたタイプに対してオーバーロードされました(したがって、暗黙の関数呼び出しになります)、それは未定義の動作ではありませんよね?