私は最初にこれらの2つの引用符を持っていましたが、今では実際にint &ref = t.mem;
は、の存続期間中に発生する必要があることを指定しているだけだと思いますt
。あなたの例では、それはどちらですか。
12.7段落1:
自明ではないデストラクタを持つオブジェクトの場合、デストラクタの実行が終了した後にオブジェクトの非静的メンバーまたは基本クラスを参照すると、未定義の動作が発生します。
そしてパラグラフ3:
オブジェクトの直接の非静的メンバーへのポインターを形成する(またはその値にアクセスする)にはobj
、の構築obj
が開始され、その破棄が完了していない必要があります。そうでない場合、ポインター値の計算(またはメンバー値へのアクセス)が行われます。未定義の動作になります。
ここに、タイプの完全なオブジェクトとタイプT
のメンバーサブオブジェクトがありint
ます。
3.8段落1:
タイプのオブジェクトの存続期間は、次の場合にT
始まります。
- タイプに適した配置とサイズのストレージ
T
が取得され、
- オブジェクトに自明でない初期化がある場合、その初期化は完了です。
タイプのオブジェクトの存続期間は、次の場合にT
終了します。
T
が自明でないデストラクタ(12.4)を持つクラス型の場合、デストラクタ呼び出しが開始されます。
- オブジェクトが占有するストレージは、再利用または解放されます。
ちなみに、3.7.3 p1:
これらの[自動ストレージ期間]エンティティのストレージは、それらが作成されたブロックが終了するまで続きます。
そして3.7.5:
メンバーサブオブジェクト、基本クラスサブオブジェクト、および配列要素の保存期間は、それらの完全なオブジェクト(1.8)の保存期間です。
exit
したがって、この例の前にコンパイラがストレージを「解放」する心配はありません。
3.8p2の非規範的なメモには、「12.6.2はベースとメンバーのサブオブジェクトの存続期間を記述している」と記載されていますが、そこでの言語は初期化とデストラクタについてのみ説明しており、「ストレージ」や「存続期間」については説明していません。些細なタイプのサブオブジェクトの「ライフタイム」の定義には影響しません。
私がこのすべてを正しく解釈している場合、renew
falseの場合、完全なクラスオブジェクトの存続期間は明示的なデストラクタ呼び出しの最後で終了しますが、int
サブオブジェクトの存続期間はプログラムの終了まで続きます。
3.8段落5と6は、オブジェクトの存続期間の前後の「割り当てられたストレージ」へのポインターと参照は、限られた方法で使用できると述べており、それらを使用して実行できない可能性のある多くのことをリストしています。ref == 42
式が要求するように、左辺値から右辺値への変換はそれらの1つですが、の存続期間がint
まだ終了していない場合は問題になりません。
ですから、私はrenew
間違っていると思いますが、プログラムは整形式でassert
成功しています!
trueのrenew
場合、ストレージはプログラムによって「再利用」されるため、元のストレージの有効期間が終了し、int
別のストレージの有効期間がint
始まります。しかし、次に3.8段落7に入ります。
オブジェクトの存続期間が終了した後、オブジェクトが占有していたストレージが再利用または解放される前に、元のオブジェクトが占有していたストレージの場所に新しいオブジェクトが作成された場合、元のオブジェクトを指すポインター、元のオブジェクトを参照するか、元のオブジェクトの名前が自動的に新しいオブジェクトを参照し、新しいオブジェクトの存続期間が開始されると、次の場合に新しいオブジェクトを操作するために使用できます。
- 新しいオブジェクトのストレージは、元のオブジェクトが占めていたストレージの場所と正確に重なっています。
- 新しいオブジェクトは元のオブジェクトと同じタイプであり(最上位のcv-qualifiersを無視します)、
- 元のオブジェクトの型はconst修飾されておらず、クラス型の場合、型がconst修飾または参照型である非静的データメンバーを含まず、
- 元のオブジェクトはタイプの最も派生したオブジェクト(1.8)で
T
あり、新しいオブジェクトはタイプの最も派生したオブジェクトですT
(つまり、これらは基本クラスのサブオブジェクトではありません)。
ここでの最初の箇条書きは、最も難しいものです。のような標準レイアウトクラスのT
場合、同じメンバーが常に同じストレージに存在する必要があります。タイプが標準レイアウトでない場合、これが技術的に必要かどうかはわかりません。
まだ使用できるかどうかref
はわかりませんが、この例には別の問題があります。
12.6.2パラグラフ8:
クラスのコンストラクターの呼び出しX
が完了した後、コンストラクターの本体の複合ステートメントX
の実行中にのメンバーが初期化されておらず、値も与えられていない場合、メンバーの値は不確定です。
t.mem
実装がゼロまたはに設定されている場合、実装は準拠していることを意味します0xDEADBEEF
(また、コンストラクターを呼び出す前に、デバッグモードが実際にそのようなことを行う場合があります)。