C++ では、
i = ++++j;
コードでは正常に動作しますが、使用すると、
i = j++++;
次のエラーが表示されます。
Operand for operator "++" must be an lvalue.
このエラーが発生するのはなぜですか?
C++ では、
i = ++++j;
コードでは正常に動作しますが、使用すると、
i = j++++;
次のエラーが表示されます。
Operand for operator "++" must be an lvalue.
このエラーが発生するのはなぜですか?
ポストインクリメントでは、オペランドが変更可能な左辺値である必要がありますが、ポストインクリメントの結果は、変更できないprvalue ( 「純粋な」右辺値) です。次の図は、何が起こっているかを示しています。
i = (j++)++ ;
^ ^
| |
| Result is a prvalue, not a valid operand for subsequent post-increment
Modifiable lvalue
左辺値と右辺値の違いを理解する必要がある場合は、C および C++の左辺値と右辺値を理解することから始めるのがよいでしょう。ドラフト C++ 標準セクションから、5.2.6
インクリメントとデクリメント [expr.post.incr]段落1には次のように書かれています (強調はこの後の引用符で私のものです):
後置 ++ 式の値は、そのオペランドの値です。[注: 取得された値は元の値のコピーです — 末尾の注]オペランドは変更可能な左辺値でなければなりません。[..]結果は prvalue です。
アップデート
C++03とC++11に関してここに違いがあるため、未定義の動作で言語を作り直しました。
最初の式が示されていますが:
i = ++++j ;
はエラーを生成しませんが、これがC++03でj
基本的な型である場合、シーケンス ポイント内でその値を複数回変更することは未定義であるため、これは未定義の動作です。古い標準草案の関連セクションは、次のように記述されているセクションExpressionsパラグラフ4になります。5
[...]前のシーケンス ポイントと次のシーケンス ポイントの間で、スカラー オブジェクトの格納値は、式の評価によって最大 1 回変更されます。さらに、保存する値を決定するためにのみ、前の値にアクセスする必要があります。この段落の要件は、完全な式の部分式の許容される順序ごとに満たされるものとします。それ以外の場合、動作は未定義です。
いくつかの例を示します。そのうちの 1 つを次に示します。
i = ++i + 1; // the behavior is undefined
C++11 では、同じスカラー オブジェクトの副作用に対する言語の変更が、同じオブジェクトの別の副作用と比較して順序付けされていない場合、動作は未定義です。したがって、これは実際にはC++11で明確に定義されており、セクション1.9
プログラムの実行パラグラフ15は次のように述べています。
特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は順不同です。[...]スカラー オブジェクトの副作用が、同じスカラー オブジェクトの別の副作用または同じスカラー オブジェクトの値を使用した値の計算と比較して順序付けされていない場合、動作は未定義です。
このようにポストインクリメントとプリインクリメントを使用すると、どちらの場合も、代入ステートメントの前または後のいずれかを使用しても、読み取り可能な (保守可能な) コードにはなりません。j +=2
後置演算子は参照ではなく値を返すため、このエラーが発生しています。しかし、明確にするために、おそらくやるべきではありませi=j++++;
ん。i = j += 2;
i = j+2; j+=2;
j+=2; i = j;