次のコードは C++ で有効ですか?
template<typename T>
class Foo {
public:
Foo(T& v) : v_(v) {}
private:
T& v_;
};
int a = 10;
Foo<int> f(a);
void Bar(int& a) {
new (&f)Foo<int>(a);
}
参照は 2 回バインドされるべきではありませんよね?
次のコードは C++ で有効ですか?
template<typename T>
class Foo {
public:
Foo(T& v) : v_(v) {}
private:
T& v_;
};
int a = 10;
Foo<int> f(a);
void Bar(int& a) {
new (&f)Foo<int>(a);
}
参照は 2 回バインドされるべきではありませんよね?
これは完全に無効です。
[basic.life]/1、強調鉱山:
タイプのオブジェクトの存続期間は、次の場合に
T
終了します。
T
自明でないデストラクタ (12.4) を持つクラス型の場合、デストラクタの呼び出しが開始されます。- オブジェクトが占有するストレージは再利用または解放されます。
配置 new はストレージを再利用し、 で示されるオブジェクトの存続期間を終了しますf
。
[basic.life]/7:
オブジェクトの有効期間が終了した後、オブジェクトが占有していたストレージが再利用または解放される前に、元のオブジェクトが占有していたストレージの場所に新しいオブジェクトが作成された場合、元のオブジェクトを指すポインタ、その参照または、元のオブジェクトの名前が新しいオブジェクトを自動的に参照し、新しいオブジェクトの有効期間が開始されると、次の場合に新しいオブジェクトを操作するために使用できます。
- 新しいオブジェクトのストレージは、元のオブジェクトが占めていたストレージの場所を正確にオーバーレイします。
- 新しいオブジェクトが元のオブジェクトと同じ型である (最上位の cv 修飾子を無視する)、および
- 元のオブジェクトの型が const 修飾されておらず、クラス型の場合、その型が const 修飾されているか参照型である非静的データ メンバーが含まれていない。
- 元のオブジェクトは型の最派生オブジェクト (1.8) で
T
あり、新しいオブジェクトは型の最派生オブジェクトですT
(つまり、基本クラスのサブオブジェクトではありません)。
Bar
3 番目の箇条書きが満たされていないため、への呼び出し後、f
は配置によって作成されたオブジェクトを参照しませんnew
が、以前にそこに存在しなくなったオブジェクトを参照し、それを使用しようとすると未定義の動作が発生します。