【问题标题】:Are moved-from objects required to be destructed?是否需要销毁移出的对象?
【发布时间】:2011-10-20 02:30:13
【问题描述】:

如果我从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 替换为区分已初始化、未初始化和移出的三值枚举。我只是想知道这是否是绝对必要的。

【问题讨论】:

  • 为什么要使用析构函数?为什么不删除?移动后,您可以将其设置为 0。
  • @balki:不确定你得到了什么。我的optional&lt;T&gt; 模板中没有动态内存,所以delete 没有任何内容。
  • 我正在实施完全相同的事情,并且有完全相同的问题!谢谢!

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


【解决方案1】:

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

【讨论】:

  • +1,我没有注意到可能调用复制构造函数的部分。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 我的移动构造函数没有调用任何析构函数...?
    • @FredOverflow 大概适用于您问题中的任何假设机制破坏已移动对象。
    • @Barry OPs 问题与用户定义的特殊成员有关,而不是如何指定语言。正如我在回答中所说,move 构造函数如何执行此任务(即在这种情况下,从 if 语句中)。
    猜你喜欢
    • 2021-06-05
    • 1970-01-01
    • 2020-04-06
    • 2012-06-25
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    相关资源
    最近更新 更多