移动派生类的构造函数

Lib*_*aul 5 c++ constructor initialization move-semantics c++11

我有两节课:

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)){}
};
Run Code Online (Sandbox Code Playgroud)

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

可以做这样的事吗?

Ser*_*sta 6

我想说,除了一点语法错误之外,您的构造是正确的,您需要base<T>在初始值设定项列表中进行限定:

\n\n
derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}\n
Run Code Online (Sandbox Code Playgroud)\n\n

首先,初始化的顺序与初始化器列表的顺序无关。草案 n4296 在12.6.2 初始化基类和成员 [class.base.init] \xc2\xa7 13中说

\n\n
\n

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

\n\n

[ 注意:强制声明顺序是为了确保基类和成员子对象以与初始化相反的顺序被销毁。\xe2\x80\x94结束注]

\n
\n\n

我们还有 \xc2\xa77 或同一章,内容如下:

\n\n
\n

每个 mem-initializer 执行的初始化构成一个完整表达式。mem-initializer 中的任何\n 表达式都将作为执行初始化的完整表达式的一部分进行计算。

\n
\n\n

我的理解是,标准规定,在班级的 move ctor 中derived,事情按以下顺序发生:

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