移动 - 构造对象与放置新 [英] move-construct object with placement new

查看:204
本文介绍了移动 - 构造对象与放置新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是不是UB通过placement new来移动构造对象?

Is it not UB to move-construct an object via placement new?

让我们说我有这个代码:

Let's say I have this code:

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_在构造完成后会有一个未定义的值(这个未定义的值来自于其移动构造函数内的未初始化的Foo f2的foo_,因为值是交换的

If it's not obvious, f1's member foo_ will have an undefined value after constructing the second foo by placement new and move construction (this undefined value comes from the uninitialized Foo f2's foo_ inside its move-constructor because the values are swapped)

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

Thus, when exiting the scope of bar(), f1's destructor will try to delete an invalid (uninitialized) pointer.

推荐答案

>这与展示位置新功能无关。这个代码会有同样的问题:

This has nothing to do with placement new. This code would have the exact same problem:

void bar() {
    Foo f1;
    Foo f2(std::move(f1));
}

每个构造的对象最终都会被破坏,无论是否使用placement-new,移动构造函数都会将移动对象置于无效状态。从对象移动并不意味着它不会被破坏。它会。

Every constructed object will get destructed eventually, so it doesn't matter if you use placement-new or not, your move-constructor messes up by leaving the moved-from object in a invalid state. Moving from an object doesn't mean it won't get destructed. It will. You have to let a valid object behind when you move from it.

Foo(Foo &&f) : foo_(nullptr) {
    std::swap(f.foo_, foo_);
}

将修复此错误。

这篇关于移动 - 构造对象与放置新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆