独自の初期化子での変数の使用


22

C ++ 20標準草案の[basic.scope.pdecl] / 1には、次の(非規範的)例が注記(プルリクエスト3580のマージ前の部分的な引用、この質問への回答を参照)に含まれていました。

unsigned char x = x;

[...] xは、独自の(不定)値で初期化されます。

これは実際にC ++ 20で明確に定義された動作を持っていますか?


一般に、フォームの自己初期化は、初期化が完了する前のの値が不定であるT x = x;ため、未定義の動作をします。不確定な値を評価すると、通常、未定義の動作([basic.indent] / 2)が発生しますが、[basic.indent] /2.3には、不確定な値を持つ左辺値から変数を直接初期化できる特定の例外があります(不確定な値で初期化が発生します) )。xunsigned charunsigned char

これだけでは、したがって、未定義の動作を引き起こすが、他のタイプの場合としないT符号なしの狭い文字タイプかそうでないstd::byte、例えばint x = x;。C ++ 17以前にも適用されたこれらの考慮事項は、下部にあるリンクされた質問も参照してください。

ただし、でもunsigned char x = x;、現在のドラフトの[basic.lifetime] / 7は次のように述べています。

同様に、オブジェクトの存続期間が始まる前に[...]その値に依存しないglvalueのプロパティを使用することは明確に定義されています。次の場合、プログラムは未定義の動作をします。

  • glvalueは、オブジェクトにアクセスするために使用されます。

  • [...]

これはx、例のの値がその存続期間中にのみ使用できることを意味するようです。

[basic.lifetime] / 1は言う:

[...]

タイプTのオブジェクトの存続期間は、次の場合に始まります。

  • [...]と
  • 初期化(存在する場合)が完了している(空の初期化を含む)([dcl.init])、

[...]

したがって、xの有効期間は、初期化が完了した後にのみ開始されます。ただし、引用された例では、の初期化が完了するx前にの値が使用されていxます。したがって、使用には未定義の動作があります。

私の分析は正しいですか?正しい場合、次のような初期化前の使用の同様のケースに影響しますか?

int x = (x = 1);

私の知る限り、C ++ 17以前でも明確に定義されていたものはどれですか。


C ++ 17(最終ドラフト)では、ライフタイムを開始するための2番目の要件が異なっていたことに注意してください。

  • オブジェクトに空でない初期化がある場合、その初期化は完了しています。

以来、xC ++ 17の定義(ただし、現在のドラフト内の1つ)によって空虚初期化しなければならず、それは上記の例に初期にアクセスされたとき、その寿命は既に始まっていることになるので、両方の例ではない未定義の動作は存在しませんでしたxC ++ 17の寿命のため。

C ++ 17以前の表現は再び異なりますが、結果は同じです。


問題は、不確定な値を使用する場合の未定義の動作に関するものではありません。これは、たとえば次の質問でカバーされています。


@LanguageLawyer私が正しいとは確信していません。特に誰もまだ回答していない場合はそうではありません。他の人が私に同意する場合は、後で提出する可能性があります(または、他の誰かが私の前に提出する可能性があります)。
クルミ

@LanguageLawyer:ワーキングペーパーが明確に間違ったことを述べている場合、編集上の問題になることはありません。
Davis Herring

1
単語はP1358によって変更されます
xskxzr

1
@xskxzrそうですね、その間、LanguageLawyerも編集上の問題を報告しました。これは、意図を明確にするためにCWGに転送されたようです。
ウォールナット

1
@ clockw0rk int x ^= x;は構文的に整形式ではありません。イニシャライザを使用した変数定義(つまりint x = x;、UBですが)またはxor割り当て式ステートメント(つまりx ^= x;xタイプがの場合はUBですが、intデフォルトで初期化され、事前に割り当てられていません)を使用できます。これら2つを1つに混在させることはできません。
クルミ

回答:


8

これは編集上の問題として公開されました。(内部での)議論のためにCWGに転送されました。約24時間後、問題を転送した人物がプルリクエスト作成し、これがUBであることを明確にするために例を変更します。

ここで、イニシャライザはライフタイムの外側の2番目の\ tcode {x}にアクセスするため、2番目の\ tcode {x}の初期化は未定義の動作を持っています\ iref {basic.life}。

その後、そのPRが追加され、問題は解決しました。したがって、明らかな解釈(存続期間が開始されていないオブジェクトにアクセスすることによるUB)が意図された解釈であることは明らかです。委員会の意図が見えるということであるこれらの構築物は、非機能的にするために、標準の非標準テキストは、これを反映するように更新されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.