[解決済み] C++17でi = i++ + 1;が合法になったのはなぜですか?
質問
未定義の動作を叫び始める前に、これは 明示的に に記載されています。 N4659 (C++17)
i = i++ + 1; // the value of i is incremented
i = i++ + 1; // the behavior is undefined
何が変わったのか?
私が調べたところでは [N4659 basic.exec】です。]
特記されている場合を除き、個々の演算子のオペランドと個々の式の部分式の評価は非シーケンスである。[演算子のオペランドの値計算は、演算子の結果の値計算の前に順序付けされる。メモリ位置の副作用が、同じメモリ位置の別の副作用または同じメモリ位置の任意のオブジェクトの値を使用する値計算のいずれかに対してシーケンスされておらず、それらが潜在的に同時でない場合、その動作は未定義である。
ここで 値 で定義されています。 [N4659 基本.type]を参照してください。
トリビアルコピー可能な型では、値表現はオブジェクト表現におけるビットのセットであり、そのビットが 値 これは、実装で定義された値の集合の1つの離散的な要素である。
から [N3337 basic.exec]を参照してください。
特記されている場合を除き、個々の演算子のオペランドと個々の式の部分式の評価は非シーケンスである。[演算子のオペランドの値計算は,演算子の結果の値計算の前に連続する。スカラオブジェクトの副作用が、同じスカラオブジェクトの別の副作用または同じスカラオブジェクトの値を使用する値計算のいずれかに対してシーケンスされていない場合、その動作は未定義である。
同様に、valueは [N3337 基本.タイプ]。
トリビアルコピー可能な型では、値表現はオブジェクト表現におけるビットのセットであり、そのビットが 値 これは、実装で定義された値の集合の1つの離散的な要素である。
並行処理について言及している以外は同一であり、重要ではありません。 メモリロケーション の代わりに スカラーオブジェクト ここで
算術型、列挙型、ポインタ型、メンバ型へのポインタ。
std::nullptr_t
そして,これらの型の cv 適合バージョンを総称してスカラ型と呼びます.
というのは、この例には影響しない。
代入演算子(=)と複合代入演算子は、すべて右から左へのグループ化です。すべて左オペランドとして変更可能な lvalue を必要とし、左オペランドを参照する lvalue を返します。左オペランドがビットフィールドの場合、結果はすべてビットフィールドになります。すべての場合において,代入は,右及び左オペランドの値計算の後,代入式の値計算の前に,順次行われる。右オペランドは、左オペランドより前に配列される。
代入演算子(=)と複合代入演算子は、すべて右から左へのグループ化です。すべて左オペランドとして変更可能な lvalue を必要とし、左オペランドを参照する lvalue を返します。左オペランドがビットフィールドの場合、結果はすべてビットフィールドになります。すべての場合において、代入は右オペランドと左オペランドの値計算の後、代入式の値計算の前にシーケンスされます。
唯一の違いは、最後の文がN3337にはないことです。
しかし、最後の文は左オペランドとして重要ではないはずです。
i
は
もう一つの副作用。
また
"同じスカラーオブジェクトの値を使用する"
として
id-式
はlvalueである。
どのように解決するのですか?
C++11では、代入の行為、つまりLHSを変更する副作用は、quot;assign"の後に続いています。 値の計算 右オペランドの これは比較的弱い保証であることに注意してください。 値計算 を使用する。については何も言っていない。 サイドエフェクト の一部ではないので、RHSに存在する可能性のある副作用の発生は 値計算 . C++11の要件では、代入行為とRHSのあらゆる副作用の間に相対的な順序が確立されていません。これが、UB の可能性を生み出しているのです。
この場合、唯一の希望は、RHSで使用される特定の演算子による追加保証です。もしRHSが接頭辞
++
の接頭辞に特有のシーケンス特性がある。
++
が、この例では救われたことでしょう。しかし、後置修飾子
++
は、そのような保証はありません。C++11では、副作用として
=
とポストフィックス
++
は、この例では互いに関連することなく終了します。そして、それがUBです。
C++17では、代入演算子の仕様に余分な文が追加されています。
右オペランドは左オペランドより前に配列される。
上記と組み合わせることで、非常に強力な保証となる。これは すべて の前に、RHS で起こること (副作用を含む) をすべて調べます。 すべて LHSで発生する 実際の代入は順番に行われるので 後 LHS (およびRHS) では、この特別なシーケンスによって、RHSに存在するあらゆる副作用から代入行為が完全に隔離されます。この強力な順序付けが、上記のUBを解消するのです。
(@John Bollinger氏のコメントを考慮して更新しました)
関連
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】f(i = -1, i = -1)の挙動が未定義なのはなぜ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】coutはstdのメンバではない
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】C++の余分な資格エラー
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++