默认移动构造函数和引用成员

Ant*_*ant 10 c++ constructor reference move c++11

从N3337的[12.8] [11]:

非联合类X的隐式定义的复制/移动构造函数执行其基础和成员的成员复制/移动.[注意:忽略非静态数据成员的大括号或大小写.另请参见12.6.2中的示例.-end note]初始化顺序与用户定义构造函数中基数和成员的初始化顺序相同(见12.6.2).让我们x为构造函数的任何参数,或者对于移动构造函数,x值指的是参数.以适合其类型的方式复制/移动每个基本或非静态数据成员:

- 如果成员是一个数组,则使用x的相应子对象直接初始化每个元素;

- 如果成员m具有右值引用类型T &&,则直接初始化为static_cast<T&&>(x.m);

- 否则,用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}'
Run Code Online (Sandbox Code Playgroud)

因此,可以安全地假设默认的移动构造函数区分成员是一个引用而且只是这样做

int& z = y;
Run Code Online (Sandbox Code Playgroud)

没有电话std::move

T.C*_*.C. 8

它由类成员访问表达式的规范处理.关键部分是

让我们x为构造函数的任何参数,或者对于移动构造函数,x值指的是参数.

换句话说,默认的移动构造函数

struct X { int x, &y; };
Run Code Online (Sandbox Code Playgroud)

相当于

X::X(X&& other) : x(std::move(other).x), y(std::move(other).y) {}
Run Code Online (Sandbox Code Playgroud)

这里重要的是类成员访问表达式的结果x.m,其中m名称是非静态数据成员,如果m具有引用类型,则总是左值,但是xvalue if x是右值并且m具有非引用类型.(参见[expr.ref]/4.)这确保左值引用成员将使用左值初始化.

  • `y(std::move(other).y)` 和 `y(other.y)` 是一样的,对吧? (2认同)