是一个`=默认`移动构造函数等价于成员移动构造函数?

这是

struct Example { int a, b; Example(int mA, int mB) : a{mA}, b{mB} { } Example(const Example& mE) : a{mE.a}, b{mE.b} { } Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { } Example& operator=(const Example& mE) { a = mE.a; b = mE.b; return *this; } Example& operator=(Example&& mE) { a = move(mE.a); b = move(mE.b); return *this; } } 

相当于这个

 struct Example { int a, b; Example(int mA, int mB) : a{mA}, b{mB} { } Example(const Example& mE) = default; Example(Example&& mE) = default; Example& operator=(const Example& mE) = default; Example& operator=(Example&& mE) = default; } 

是的,两者是一样的。

 struct Example { int a, b; Example(int mA, int mB) : a{mA}, b{mB} { } Example(const Example& mE) = default; Example(Example&& mE) = default; Example& operator=(const Example& mE) = default; Example& operator=(Example&& mE) = default; } 

该版本将允许您跳过正文定义。

但是,当你声explicitly-defaulted-functions时,你必须遵循一些规则:

8.4.2显式默认函数[dcl.fct.def.default]

表单的函数定义:

  attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt = default ; 

被称为显式默认定义。 明确违约的function应该

  • 成为特殊的会员function,

  • 具有相同的声明函数types(可能有不同的ref-qualifiers除外,除了在复制构造函数或复制赋值运算符的情况下,参数types可以是“对非const T引用”,其中T是成员函数的类),就像它已经被隐式声明一样,

  • 没有默认参数。

是的,默认的移动构造函数将执行其基础和成员的成员移动,所以:

 Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { } 

相当于:

 Example(Example&& mE) = default; 

我们可以通过阅读C ++ 11标准部分的草案来看到这一点12.8 复制和移动类对象的13段( 强调我的前进 ):

默认的复制/移动构造函数默认为隐式定义 (3.2),或者在第一次声明后显式默认复制/移动构造函数。 [注:拷贝/移动构造函数是隐式定义的,即使这个实现没有使用odr(3.2,12.2)。 – 注意] […]

15段说:

非工会类X的隐式定义的复制/移动构造函数 执行其基础和成员的成员复制/移动 。 [注意:非静态数据成员的括号或相等初始值设定项被忽略。 参见12.6.2中的例子。 -end note]初始化的顺序与用户定义的构造函数中的基础和成员的初始化顺序相同(见12.6.2)。 设x是构造函数的参数,或者对于移动构造函数,是指参数的xvalue。 每个基本或非静态数据成员都以适合其types的方式复制/移动:

  • 如果该成员是一个数组,则每个元素都用x的相应子对象直接初始化;
  • 如果成员m有右值引用typesT &&,则用static_cast(xm)直接初始化;
  • 否则,基础或成员直接初始化为x的对应基础或成员。

虚拟基类子对象只能由隐式定义的复制/移动构造函数初始化一次(见12.6.2)。

除了非常病态的病例…是的。

更确切地说,你还必须考虑最终的基础, Example可能有完全相同的规则。 首先是基地申报单,然后是成员,总是按照申报的顺序。