我有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
变为无效,但我仍然需要它来使用它&#39 ; t2
初始化
有可能做这样的事吗?
答案 0 :(得分:3)
我会说你的构造是正确的,除了一点语法错误,你需要在初始化列表中限定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-initializers的顺序如何)。
(13.4) - 最后,执行构造函数体的复合语句。[注意:声明命令的目的是确保基础和成员子对象在销毁中被销毁 初始化的逆序。 - 后注]
我们还有§7或同一章说:
每个mem-initializer执行的初始化构成一个完整表达式。任何 mem-initializer中的表达式被计算为执行初始化的完整表达式的一部分。
我的理解是标准说在derived
类的移动ctor中,事情按顺序发生: