move-construct object with placement new

Bog*_*tza 2 c++ placement-new move-constructor c++11

是不是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
}
Run Code Online (Sandbox Code Playgroud)

如果不明显,f1的成员foo_将在构造第二个foo后通过放置new和move构造得到一个未定义的值(这个未定义的值来自未初始化的Foo f2在其move-constructor中的foo_,因为值是交换的)

因此,当退出bar()的范围时,f1的析构函数将尝试删除无效(未初始化)指针.

tka*_*usl 5

这与放置新内容无关.这段代码会有完全相同的问题:

void bar() {
    Foo f1;
    Foo f2(std::move(f1));
}
Run Code Online (Sandbox Code Playgroud)

每个构造的对象最终都会被破坏,所以无论你是否使用placement-new都没关系,你的move-constructor会让被移动的对象处于无效状态而混乱.从物体移动并不意味着它不会被破坏.它会.当你离开它时,你必须让一个有效的对象落后.

Foo(Foo &&f) : foo_(nullptr) {
    std::swap(f.foo_, foo_);
}
Run Code Online (Sandbox Code Playgroud)

将修复该错误.