技術的には、これは全体として未定義動作です。
しかし、答えには2つの重要な側面があります。
コードステートメント:
std::cout << a++ << a;
次のように評価されます:
std::operator<<(std::operator<<(std::cout, a++), a);
この標準では、関数の引数の評価順序は定義されていません。
だからどちらか:
std::operator<<(std::cout, a++)
最初に評価されるか
a
最初に評価されるか
- 実装で定義された順序である可能性があります。
この順序は、標準では指定されていません[参照1] 。
[参照1] C++035.2.2関数呼び出し
パラ8
引数の評価の順序は指定されていません。引数式の評価のすべての副作用は、関数に入る前に有効になります。後置式と引数式リストの評価順序は未定です。
さらに、関数への引数の評価の間にシーケンスポイントはありませんが、シーケンスポイントは、すべての引数の評価後にのみ存在します[参照2]。
[参照2] C++ 03 1.9プログラムの実行[intro.execution]:
パラ17:
関数を呼び出す場合(関数がインラインであるかどうかに関係なく)、すべての関数の引数(存在する場合)の評価後、関数本体の式またはステートメントの実行前に実行されるシーケンスポイントがあります。
ここで、の値はc
、介在するシーケンスポイントなしで複数回アクセスされていることに注意してください。これに関して、標準では次のように述べられています。
[参照3] C++ 03 5式[expr]:
パラ4:
....
前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。さらに、前の値は、保存される値を決定するためにのみアクセスされるものとします。この段落の要件は、完全な式の部分式の許容される順序ごとに満たされるものとします。それ以外の場合、動作は未定義です。
コードはc
、シーケンスポイントを介さずに複数回変更され、保存されたオブジェクトの値を決定するためにアクセスされていません。これは上記の条項の明らかな違反であり、したがって、標準で義務付けられている結果は未定義動作です[参照3]。