使用 placement new 更新参考成员?
Using placement new to update a reference member?
下面的代码在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);
}
引用不应该绑定两次,对吧?
它可能是合法的,但它的风格非常糟糕。 placement new 的参数是一个 void*,所以你告诉 C++ reinterpret_cast f 的地址作为一个 void*,然后使用它作为构造新东西的位置——覆盖原来的 f.
基本上,不要那样做。
这是完全无效的。
[basic.life]/1,强调我的:
The lifetime of an object of type T
ends when:
- if
T
is a class type with a non-trivial destructor (12.4), the destructor call starts, or
- the storage which the object occupies is reused or released.
placement new 重用了存储,结束了f
表示的对象的生命周期。
[basic.life]/7:
If, after the lifetime of an object has ended and before the storage
which the object occupied is reused or released, a new object is
created at the storage location which the original object occupied, a
pointer that pointed to the original object, a reference that referred
to the original object, or the name of the original object will
automatically refer to the new object and, once the lifetime of the
new object has started, can be used to manipulate the new object, if:
- the storage for the new object exactly overlays the storage location which the original object occupied, and
- the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
- the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is
const-qualified or a reference type, and
- the original object was a most derived object (1.8) of type
T
and the new object is a most derived object of type T
(that is, they are
not base class subobjects).
由于不满足第三个要点,在调用Bar
后,f
不引用放置new
创建的对象,而是指向no-以前存在的寿命更长的对象,并尝试使用它会导致未定义的行为。
下面的代码在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);
}
引用不应该绑定两次,对吧?
它可能是合法的,但它的风格非常糟糕。 placement new 的参数是一个 void*,所以你告诉 C++ reinterpret_cast f 的地址作为一个 void*,然后使用它作为构造新东西的位置——覆盖原来的 f.
基本上,不要那样做。
这是完全无效的。
[basic.life]/1,强调我的:
The lifetime of an object of type
T
ends when:
- if
T
is a class type with a non-trivial destructor (12.4), the destructor call starts, or- the storage which the object occupies is reused or released.
placement new 重用了存储,结束了f
表示的对象的生命周期。
[basic.life]/7:
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
- the storage for the new object exactly overlays the storage location which the original object occupied, and
- the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
- the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
- the original object was a most derived object (1.8) of type
T
and the new object is a most derived object of typeT
(that is, they are not base class subobjects).
由于不满足第三个要点,在调用Bar
后,f
不引用放置new
创建的对象,而是指向no-以前存在的寿命更长的对象,并尝试使用它会导致未定义的行为。