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

Default move constructor and reference members

本文关键字:引用 成员 构造函数 移动 默认      更新时间:2023-10-16

来自N3337的[12.8][11]:

非并集类X的隐式定义的复制/移动构造函数执行其基和成员的成员式复制/移动。[注意:忽略非静态数据成员的大括号或相等初始值设定项。另请参阅12.6.2中的示例--end note]初始化的顺序与用户定义构造函数中基和成员的初始化顺序相同(见12.6.2)。设x为构造函数的参数,或者对于move构造函数,为引用该参数的xvalue。每个基本或非静态数据成员都以适合其类型的方式进行复制/移动:

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

--如果成员m具有右值引用类型T&,用CCD_ 2直接初始化;

--否则,该基或成员直接用x的相应基或成员初始化。

这实际上更像是一个澄清,但我看不到该子句中有任何提及lvalue引用成员的内容。由于它没有提到它们,默认情况下,它似乎说它们是隐式成员移动的一部分,但以下内容不起作用;

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}'

那么,假设默认的move构造函数将成员区分为引用,并且只执行,这是否安全

int& z = y;

没有呼叫std::move

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

x为构造函数的参数,或者对于move构造函数,为引用该参数的xvalue。

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

struct X { int x, &y; };

的等价物吗

X::X(X&& other) : x(std::move(other).x), y(std::move(other).y) {}

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