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

时间:2015-10-27 22:06:37

标签: c++ c++11 constructor reference move

来自N3337的[12.8] [11]:

  

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

     

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

     

- 如果成员m具有右值参考类型T&amp;&amp;,则使用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}'

因此,可以安全地假设默认移动构造函数区分成员是引用而只是执行

int& z = y;

没有拨打std::move

1 个答案:

答案 0 :(得分:6)

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

  

declare @member_location int = 10 ,@id int = 2; -- CTE to populate data with TestTable as ( select * from ( values (2 , 32 , 10), (3 , 35 , 7), (4 , 40 , 10), (5 , 15 , 5), (6 , 10 , 10), (7 , 65 , 10) ) V(id,reputation_total_points,member_location) ) -- Main Query select res.z from ( select id, z = COUNT_BIG(*) over ( Order by reputation_total_points desc ) from TestTable where member_location = @member_location ) res where id = @id 成为构造函数的参数,或者对于移动构造函数,使用引用该参数的xvalue。

换句话说,

的默认移动构造函数
x

相当于

struct X { int x, &y; };

重要的是,如果X::X(X&& other) : x(std::move(other).x), y(std::move(other).y) {} 具有引用类型,则类成员访问表达式x.m的结果(m命名非静态数据成员)始终是左值,但是如果m是右值而x具有非引用类型,则为xvalue。 (参见[expr.ref] / 4。)这确保左值引用成员将使用左值初始化。