从需要销毁的对象中移动

Are moved-from objects required to be destructed?

本文关键字:对象 移动      更新时间:2023-10-16

如果我从b中移动构建a,是否仍然有必要破坏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,该枚举可以区分初始化、未初始化和移出。我只是想知道这是否绝对必要

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

是的,您仍然需要销毁它们。例如,可以显示此缺陷的设计之一是基于观察者的模式,其中一个对象保留指向另一个对象的指针列表。不运行析构函数不会移除指针,当代码试图访问一个不再存在的对象时,代码会崩溃。

在您的示例中,更简单的事情是在移动-from对象中不将initialized设置为false。在被移出后,值仍然被定义为处于有效状态,并且您所引用的右值的析构函数将在没有进一步干预的情况下清除它。

我想对你的问题回答"不",但我不确定这是不是一个正确的问题。考虑以下内容:

{  // start of scope
    T maybe_moved;
    if(some_condition) {
        T(std::move(maybe_moved));
    }
// end of scope
}
对于maybe_moved对象,

T::~T()显然应该只调用一次。如果move构造函数调用它,您将如何使这些无害的代码工作?