使用placement new来更新引用成员?

xia*_*.li 3 c++ reference placement-new object-lifetime reference-binding

以下代码在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);
}
Run Code Online (Sandbox Code Playgroud)

引用不应该被绑定两次,对吧?

T.C*_*.C. 9

这完全无效.

[basic.life]/1,强调我的:

类型对象的生命周期在以下情况T结束:

  • 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者
  • 对象占用的存储器被重用或释放.

placement new重用存储,结束表示的对象的生命周期f.

[basic.life]/7:

如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,则在原始对象占用的存储位置创建新对象,指向原始对象的指针,引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以用来操纵新对象,如果:

  • 新对象的存储完全覆盖原始对象占用的存储位置,以及
  • 新对象与原始对象的类型相同(忽略顶级cv限定符),和
  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定的非静态数据成员或引用类型,以及
  • 原始对象是类型最派生的对象(1.8),T新对象是类型最派生的对象T(也就是说,它们不是基类子对象).

由于第三个项目符号点不满足,在调用之后Bar,f不会引用由放置创建的对象new,而是引用之前不再生活的对象,并且尝试使用它会导致未定义的行为.

另见CWG1776P0137R0.