移动 - 需要被破坏的物体?

时间:2011-08-04 15:05:21

标签: c++ c++11 destructor rvalue-reference move-semantics

如果我从a移动构建b,是否仍然必要来破坏b,或者我可以在没有这样做的情况下离开?

在实施optional<T>模板期间,我突然想到了这个问题。摘录:

~optional()
{
    if (initialized)
    {
        reinterpret_cast<T*>(data)->~T();
    }
}

optional(optional&& o) : initialized(o.initialized)
{
    if (initialized)
    {
        new(data) T(std::move(*o));   // move from o.data
        o.initialized = false;        // o.data won't be destructed anymore!
    }
}

当然,我可以用一个三值枚举替换bool initialized,它可以区分初始化,非初始化和移动。我只是想知道这是否是绝对必要的。

3 个答案:

答案 0 :(得分:14)

是的,仍有必要销毁b。从对象移动是一个有效的构造对象。在某些情况下,它甚至可能拥有仍需要处理的资源。在您展示的通用代码中,T甚至可能没有移动构造函数。在这种情况下,您可以调用复制构造函数。所以你绝对不能假设~T()是无操作并且可以省略。

答案 1 :(得分:3)

是的,你仍然需要破坏它们。可以显示这个缺陷的设计之一是,例如,基于观察者的模式,其中一个对象保持指向另一个对象的列表。不运行析构函数将不会删除指针,并且当代码尝试访问不再存在的对象时代码将崩溃。

在您的示例中,更容易做的事情就是在移动对象中不将初始化设置为false。在移动之后,该值仍被定义为处于有效状态,并且您所引用的右值的析构函数将在没有进一步干预的情况下对其进行清理。

答案 2 :(得分:2)

我想对你的问题回答'不',但我不确定这是否是正确的问题。请考虑以下事项:

{  // start of scope
    T maybe_moved;
    if(some_condition) {
        T(std::move(maybe_moved));
    }
// end of scope
}
{p> T::~T()显然只应为maybe_moved对象调用一次。如果一个移动构造函数会调用它,你会如何使这样无害的代码工作?