The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members. [ Note: brace-or-equal-initializers of non-static data members are ignored. See also the example in 12.6.2. —end note ] The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Let
x
be either the parameter of the constructor or,for the move constructor,an xvalue referring to the parameter. Each base or non-static data member is copied/moved in the manner appropriate to its type:— if the member is an array,each element is direct-initialized with the corresponding subobject of x;
— if a member m has rvalue reference type T&&,it is direct-initialized with
static_cast<T&&>(x.m)
;— otherwise,the base or member is direct-initialized with the corresponding base or member of x.
这实际上是一个澄清,但我看不到在该子句中提到左值引用成员.由于它没有提到它们,默认情况下似乎说它们是隐式成员移动的一部分,但是以下方法不起作用;
int x = 5; int& y = x; int& z(std::move(y)); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'std::remove_reference<int&>::type {aka int}'
因此,可以安全地假设默认的移动构造函数区分成员是一个引用而且只是这样做
int& z = y;
没有调用std :: move?
解决方法
Let
x
be either the parameter of the constructor or,an xvalue referring to the parameter.
换句话说,默认的移动构造函数
struct X { int x,&y; };
相当于
X::X(X&& other) : x(std::move(other).x),y(std::move(other).y) {}
这里重要的是,类成员访问表达式xm的结果,其中m表示非静态数据成员,如果m具有引用类型,则始终为左值,但如果x是右值,则x值为x值,m为非引用类型. (参见[expr.ref] / 4.)这确保左值引用成员将使用左值初始化.