移动派生类的构造函数

自由保​​罗

我有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初始化

可以做这样的事情吗?

Serge Ballesta

我会说您的构造是正确的,除了一些语法错误之外,您需要base<T>在初始化列表中进行限定

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)的构造函数,虚拟基类将按照它们出现在深度优先左的顺序进行初始化基类的有向无环图的从右到右遍历,其中“从左到右”是基类在派生类base-specifier-list中的出现顺序。
(13.2)—然后,直接基类按照它们出现在base-specifier-list中的声明顺序进行初始化(与mem-initializers的顺序无关)。
(13.3)—然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,无论mem-initializer的顺序如何)。
(13.4)—最后,执行构造函数主体的复合语句。

[注意:声明顺序是强制执行的,以确保以相反的初始化顺序销毁基础和成员子对象。—尾注]

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

每个mem初始化程序执行的初始化构成一个完整表达式。mem初始化程序中的任何表达式都将作为执行初始化的全表达式的一部分进行评估。

我的理解是,标准表示在类的移动ctor中derived,事情按以下顺序发生:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章