2015-10-27 21 views
6

Da [12.8] [11] del N3337:mossa di default del costruttore e di riferimento membri

Il costruttore di copia/spostamento implicitamente definito per un non-union classe X esegue un membro a membro di copia/spostamento delle sue basi e membri. [Nota: gli inizializzatori brace-or-equal di membri di dati non statici vengono ignorati. Vedi anche l'esempio in 12.6.2. -end note] L'ordine di inizializzazione è lo stesso dell'ordine di inizializzazione di basi e membri in un costruttore definito dall'utente (vedere 12.6.2). Sia x il parametro del costruttore o, per il costruttore di movimento, un valore x che si riferisce al parametro. Ogni membro di dati di base o non statico viene copiato/spostato nel modo appropriato al suo tipo:

- se il membro è un array, ciascun elemento viene inizializzato direttamente con il corrispondente suboject di x;

- se un membro m ha il tipo di riferimento rvalore T & &, viene inizializzato direttamente con static_cast<T&&>(x.m);

- in caso contrario, la base o il membro viene inizializzato direttamente con la base o membro corrispondente di x.

Questo è davvero più di un chiarimento, ma non riesco a vedere alcuna menzione dei membri di riferimento di lvalue in quella clausola. Dal momento che non li menziona, per impostazione predefinita sembra dire che fanno parte della mossa implicita membro, tuttavia il seguente non funzionerebbe;

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

Quindi è lecito ritenere che il costruttore di default mossa distingue che un membro è un riferimento e sarebbe semplicemente fare

int& z = y; 

con nessuna chiamata per std::move?

+0

Un riferimento lvalue non può essere associato a un valore x, quindi 'int & z (std :: move (y));' non è legale. 'int &z = y;' è legale e rende 'z' un terzo nome per l'oggetto' int' che è attualmente chiamato 'x' e' y'. Non sono sicuro di quale sia la tua domanda? –

+0

"direct-initialized" significa che per un membro 'm', è inizializzato come se fosse' T m (other.m); ' –

+0

Penso che questo sia correlato a (ed eventualmente risolto da) http: // stackoverflow.it/questions/33344259/does-rvo-work-on-object-members – Sheljohn

risposta

6

Viene gestito dalle specifiche delle espressioni di accesso dei membri della classe. La parte chiave è

Lasciare x essere il parametro del costruttore o, per il costruttore di movimento, un valore x che fa riferimento al parametro.

In altre parole, un costruttore mossa stabilizzato per

struct X { int x, &y; }; 

esegue l'equivalente di

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

La cosa importante è che il risultato di un accesso un'espressione membro della classe x.m, dove m nomi un membro di dati non statici, è sempre un lvalue se m ha un tipo di riferimento, ma un valore x se x è un valore e m ha un tipo non di riferimento. (Vedi [expr.ref]/4.) Questo assicura che i membri di riferimento di lvalue vengano inizializzati con lvalue.

+1

'y (std :: move (altro) .y)' è uguale a 'y (other.y)', giusto? –

+0

@ M.M Destra, per riferimento digitata 'y'. –

Problemi correlati