Default Move Constructor and Reference Elements

From [12.8] [11] of N3337:

An implicit copy / move constructor for a non-unit class X performs a phased copy / move of its bases and elements. [Note: copied or equal initializers of non-static data members are ignored. See also the example in 12.6.2. -end note] The initialization order is the same as the initialization order of the bases and members in a user-defined constructor (see 12.6.2). Let x be either the constructor parameter, or, for the displacement constructor, the value x related to the parameter. Each basic or non-static data element is copied / moved according to its type:

- if the element is an array, each element is directly initialized by the corresponding subobject x;

- if the element m has the reference type rvalue T & &, it is directly initialized using static_cast<T&&>(xm) ;

- otherwise, the base or element is initialized with a direct base or element x.

This is really more explanation, but I don't see any mention of lvalue reference elements in this section. Since he does not mention them, by default it seems that they are part of an implicit member movement, but the following will not work;

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

So, is it possible to assume that the default constructor of move distinguishes that the element is a link and simply just executes

 int& z = y; 

without calling std::move ?

+6
c ++ constructor reference c ++ 11 move
source share
1 answer

It is processed by the specification of class member access expressions. Key part

Let x be either the constructor parameter, or, for the displacement constructor, the value x related to the parameter.

In other words, the default move constructor for

 struct X { int x, &y; }; 

does it have an equivalent

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

The important thing is that the result of expressing access to a member of class xm , where m denotes a non-static data element, is always an lvalue if m has a reference type, but the value x if x is an rvalue and m is not a reference type. (See [Expr.ref] / 4.) This ensures that lvalue reference elements are initialized by lvalues.

+6
source share

All Articles