【问题标题】:Move constructor for derived class移动派生类的构造函数
【发布时间】:2016-10-06 17:47:43
【问题描述】:

我有 2 节课:

template<typename T>
class base{
    T t;
public:
    base(base &&b): t(std::move(b.t)){}
};

template<typename T, typename T2>
class derived : protected base<T>{
    T2 t2;
public:
    derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}
};

我将整个 d 对象移动到 derived move-constructor 中以初始化 base 部分,d 变得无效,但我仍然需要它来使用它的部分进行 t2 初始化

这样的事情有可能吗?

【问题讨论】:

  • 我很确定 t2(std::move(t2)) 要么不会编译,要么是未定义的行为。
  • base(std::move(d)) 有点像移动切片。 base 只知道 t 并且只移动 t,但这会让您感到不舒服,因为在移动之后对象需要安全地丢弃,此时只有 base 满足该要求。 Crom 只知道derived::t2 中的内容。但这对于任何派生对象都是正确的。您永远无法移动派生对象,这太疯狂了。只要在derived 的移动完成后,derived 就可以被处理掉,我想你就可以走了。移动dbase 部分,然后移动dderived 部分。
  • std::move 实际上并没有移动任何东西,它只是对右值引用的强制转换。移动构造函数是实际修改数据的对象。而且您知道,在您的情况下,base 移动构造函数不会使d.t2 无效。我相信你的代码是正确的。
  • 这很好...base(std::move(d)) 可能会导致dbase 部分“无效”(无论是什么,它都可能被归零等).. . 但是派生类型的其余部分仍然可以通过d.t2 安全访问...base 移动构造函数将无法触及它
  • 代码应该是正确的,但是,为了清楚起见,我会在第一步添加static_cast。这意味着实际上仅移动了对象的基础部分。这不会对代码产生任何实际影响。

标签: c++ c++11 constructor initialization move-semantics


【解决方案1】:

我会说你的构造是正确的,除了一点语法错误,你需要在初始化列表中限定base&lt;T&gt;

derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}

首先,初始化的顺序与初始化列表的顺序无关。 n4296 草案在 12.6.2 初始化基础和成员 [class.base.init] § 13

中说

在非委托构造函数中,初始化按以下顺序进行:
(13.1) — 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类在 它们出现在基类的有向无环图的深度优先从左到右遍历中的顺序, 其中“从左到右”是派生类基说明符列表中基类的出现顺序。
(13.2) — 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化 (不管 mem-initializers 的顺序如何)。
(13.3) — 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化 (同样不管 mem-initializers 的顺序如何)。
(13.4) — 最后,执行构造函数体的复合语句。

[ 注意:声明顺序必须确保基子对象和成员子对象在 初始化的相反顺序。 ——尾注]

我们也有 §7 或同一章说:

每个 mem-initializer 执行的初始化构成一个完整的表达式。任何 mem-initializer 中的表达式被评估为执行初始化的完整表达式的一部分。

我的理解是,标准规定在 derived 类的移动 ctor 中,事情是按这个顺序发生的:

  • 基类的移动 ctor 被调用
    • 然后它为 T 调用 move ctor,有效地构造目标的 t 成员并最终将源的 t 成员归零
  • 调用了 T2 对象的移动 ctor - 在那一刻,完整表达式的结尾还没有到达,只有 source 的 t 成员最终被销毁
  • 在完整语句的末尾,源对象处于未确定状态,不应再使用。

【讨论】:

    猜你喜欢
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 2020-02-28
    • 2011-12-29
    • 1970-01-01
    • 2020-11-28
    • 2018-07-21
    相关资源
    最近更新 更多