以下代码在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);
}
引用不应该绑定两次,对吧?
答案 0 :(得分:9)
这完全无效。
[basic.life] / 1,强调我的:
类型
T
的对象的生命周期在以下时间结束:
- 如果
T
是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者- 对象占用的存储空间被重用或释放。
placement new重用存储,结束由f
表示的对象的生命周期。
[basic.life] / 7:
如果在对象的生命周期结束之后和存储之前 对象占用的是重用或释放的,一个新的对象是 在原始对象占用的存储位置创建,a 指向原始对象的指针,引用的引用 到原始对象,或原始对象的名称 自动引用新对象,一旦生命周期 新对象已启动,可用于操作新对象,如果:
- 新对象的存储空间正好覆盖原始对象占用的存储位置,
- 新对象与原始对象的类型相同(忽略顶级cv限定符),
- 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为的非静态数据成员 const限定或引用类型和
- 原始对象是类型为
T
的派生程度最高的对象(1.8),新对象是类型为T
的派生程度最高的对象(即它们是 不是基类子对象)。
由于第三个项目符号点不满意,在致电Bar
后,f
并未引用展示位置new
创建的对象,而是不再涉及之前存在的生物对象,并且试图使用它会导致未定义的行为。
答案 1 :(得分:0)
这可能是合法的,但它的风格非常糟糕。放置new的参数是void *,所以你告诉C ++将f的地址重新解释为一个void *,然后用它作为构造新东西的位置 - 覆盖原始的f。
基本上,不要这样做。