通过放置new来移动构造对象不是UB吗?
我们说我有这段代码:
class Foo {
public:
Foo() { foo_ = new int; }
~Foo() { delete foo_; }
Foo(Foo &&f) {
foo_ = std::swap(f.foo_, foo_);
}
private:
int* foo_;
}
void bar() {
void* pMem = malloc(sizeof(Foo));
Foo f1;
// move-construct with placement new:
new((Foo*)pMem) Foo(std::move(f1)); // f2 in *pMem
// now f1 will contain a pointer foo_ of undefined value
// when exiting scope f1.~Foo(){} will exhibit UB trying to delete it
}
如果不明显,f1的成员foo_将通过放置new和move构造构造第二个foo后具有未定义的值(这个未定义的值来自未初始化的Foo f2&f; foo_在其move-constructor中,因为值交换)
因此,当退出bar()的范围时,f1'析构函数将尝试删除无效(未初始化)的指针。
答案 0 :(得分:5)
这与放置新内容无关。这段代码会有完全相同的问题:
void bar() {
Foo f1;
Foo f2(std::move(f1));
}
每个构造的对象最终都会被破坏,所以如果你使用placement-new也没关系,你的move-constructor会把移动的对象留在无效的状态。从物体移动并不意味着它不会被破坏。它会。当你离开它时,你必须让一个有效的物体落后。
Foo(Foo &&f) : foo_(nullptr) {
std::swap(f.foo_, foo_);
}
将修复错误。