移动派生的构造函数 class
Move constructor for derived class
我有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
初始化部分
这样的事情可以做吗?
我会说你的构造是正确的,除了一点语法错误,你需要在初始化列表中限定 base<T>
:
derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}
首先,初始化顺序与初始化列表的顺序无关。 n4296 草案在 12.6.2 Initializing bases and members [class.base.init] § 13
中说
In a non-delegating constructor, initialization proceeds in the following order:
(13.1) — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in
the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,
where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
(13.2) — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).
(13.3) — Then, non-static data members are initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).
(13.4) — Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. —end note ]
我们也有 §7 或同一章说:
The initialization performed by each mem-initializer constitutes a full-expression. Any
expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization.
我的理解是,标准规定在 derived
class 的移动构造函数中,事情按以下顺序发生:
- 调用基 class 的移动构造函数
- 依次为 T 调用 move ctor 有效地构造 target 的 t 成员并最终将 source 的 t 成员归零
- 调用了 T2 对象的 move ctor - 在那一刻,还没有到达完整表达式的末尾,最终只有源的 t 个成员被销毁
- 在完整语句的末尾,源对象处于未确定状态,不应再使用。
我有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
初始化部分
这样的事情可以做吗?
我会说你的构造是正确的,除了一点语法错误,你需要在初始化列表中限定 base<T>
:
derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}
首先,初始化顺序与初始化列表的顺序无关。 n4296 草案在 12.6.2 Initializing bases and members [class.base.init] § 13
中说In a non-delegating constructor, initialization proceeds in the following order:
(13.1) — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
(13.2) — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
(13.3) — Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
(13.4) — Finally, the compound-statement of the constructor body is executed.[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. —end note ]
我们也有 §7 或同一章说:
The initialization performed by each mem-initializer constitutes a full-expression. Any expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization.
我的理解是,标准规定在 derived
class 的移动构造函数中,事情按以下顺序发生:
- 调用基 class 的移动构造函数
- 依次为 T 调用 move ctor 有效地构造 target 的 t 成员并最终将 source 的 t 成员归零
- 调用了 T2 对象的 move ctor - 在那一刻,还没有到达完整表达式的末尾,最终只有源的 t 个成员被销毁
- 在完整语句的末尾,源对象处于未确定状态,不应再使用。