web-dev-qa-db-ja.com

C ++ 14での不確定な値の使用と未定義の動作に関して、C ++標準は変更されましたか?

で説明されているように、初期化には左辺値から右辺値への変換が必要ですか? int x = x; UBですか? C++標準のセクション3.3.2宣言のポイントに驚くべき例があります。 intは、それ自体の不確定な値で初期化されます。

int x = 12;
{ int x = x; }

ここで、2番目のxはそれ自体の(不確定な)値で初期化されます。 —end example]

この質問に対するヨハネスの回答が示すのは、左辺値から右辺値への変換が必要なため、未定義の動作です。

最新のC++ 14ドラフト標準N3936で見つけることができます ここ この例は次のように変更されました:

unsigned char x = 12;
{ unsigned char x = x; }

ここで、2番目のxはそれ自体の(不確定な)値で初期化されます。 —end example]

例でこの変更を推進した不確定な値と未定義の動作に関して、C++ 14で何か変更がありましたか?

62
Shafik Yaghmour

はい、この変更は言語の変更によって引き起こされたため、未定義の動作になります評価によって不確定な値が生成された場合ただし、符号なしの狭い文字を除きます。

欠陥レポート1787 提案されたテキストは N3914 にあります1 だった 最近2014年に承認されました そして最新のワーキングドラフトに組み込まれていますN3936

不確定な値に関して最も興味深い変更は、セクション8.5段落12になります。

オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。初期化が実行されない場合、自動または動的な保存期間を持つオブジェクトの値は不確定です。 [注:静的またはスレッドストレージ期間のオブジェクトはゼロで初期化されます。3.6.2を参照してください。 — エンドノート]

to(emphasis mine):

オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。自動または動的な保存期間を持つオブジェクトのストレージが取得されると、オブジェクトには不確定値があり、オブジェクトの初期化が実行されない場合、そのオブジェクトは、その値が置き換えられるまで不確定値を保持します( 5.17 [expr.ass])。 [注:静的またはスレッドストレージ期間のオブジェクトはゼロで初期化されます。3.6.2[basic.start.init]を参照してください。 —end note]評価によって不確定な値が生成された場合、次の場合を除いて動作は定義されていません

  • 符号なしの狭い文字タイプ(3.9.1 [basic.fundamental])の不確定な値が、次の評価によって生成された場合:

    • 条件式の2番目または3番目のオペランド(5.16 [expr.cond])、

    • コンマの右オペランド(5.18 [expr.comma])、

    • キャストまたは符号なしナロー文字タイプへの変換のオペランド(4.7 [conv.integral]、5.2.3 [expr.type.conv]、5.2.9 [expr.static.cast]、5.4 [expr.cast]) 、または

    • 破棄された値の式(第5節[expr])、

    その場合、演算の結果は不確定な値になります。

  • 符号なしナロー文字タイプ(3.9.1 [basic.fundamental])の不確定値が、最初のオペランドがunsignedナローの左辺値である単純代入演算子(5.17 [expr.ass])の右オペランドの評価によって生成される場合文字タイプの場合、不確定な値は、左側のオペランドによって参照されるオブジェクトの値を置き換えます。

  • 符号なし狭文字型のオブジェクトを初期化する際の初期化式の評価により、符号なし狭文字型(3.9.1 [basic.fundamental])の不確定値が生成された場合、そのオブジェクトは不確定な値に初期化されます。

次の例が含まれています。

[例:

int f(bool b) {
  unsigned char c;
  unsigned char d = c; // OK, d has an indeterminate value
  int e = d;           // undefined behavior
  return b ? d : 0;    // undefined behavior if b is true
}

終了例]

このテキストは N3936 現在の 作業ドラフト にあり、N3937C++14 DISです。

C++ 1yより前

このドラフトの前は、C 不定値の使用が未定義であるという明確な概念が常にありました C++とは異なり、不定値という用語を定義せずに使用していたことに注意してください(C99から定義を借用できないと仮定)および 欠陥レポート616を参照指定不足の左辺値から右辺値への変換 に依存する必要がありました。これは ドラフトC++ 11標準 でセクション4.1Lvalue-値への変換段落1これは次のように述べています:

[...]オブジェクトが初期化されていない場合、この変換を必要とするプログラムの動作は未定義です。[...]


脚注:

  1. 1787欠陥レポート616 の改訂版であり、その情報は N39 にあります。
53
Shafik Yaghmour