move-construct object with placement new

时间:2016-07-03 16:27:30

标签: c++ c++11 placement-new move-constructor

通过放置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'析构函数将尝试删除无效(未初始化)的指针。

1 个答案:

答案 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_);
}

将修复错误。