10

如果我 move-construct afrom b,是否仍然需要destruct 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一个区分已初始化、未初始化和移出的三值枚举。我只想知道这是否是绝对必要的。

4

3 回答 3

14

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

于 2011-08-04T15:24:17.663 回答
3

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

在您的示例中更容易做的事情就是不要在移出的对象中将 initialized 设置为 false 。该值在被移出后仍被定义为处于有效状态,并且您所指的右值的析构函数将清理它而无需进一步干预。

于 2011-08-04T15:21:23.213 回答
2

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

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

T::~T()显然应该只为maybe_moved对象调用一次。如果移动构造函数调用它,你将如何让这些无害的代码工作?

于 2011-08-04T15:25:06.063 回答