Rvalue Ritenence of Lvalue Reference vs Rvalue Riferimento di lvalue / rvalue
Domanda
È legale avere una ritenzione rvalue di un riferimento di lvalue?
Considerando il seguente esempio, esiste una differenza tra i due casi nell'ultimo rvalueref in termini di ciò che fa riferimento o digitare (o altre cose)?
Type& ref = GetReference()
Type&& rvalueRef = std::move(ref)
vs
Type value = GetValue()
Type&& rvalueRef = std::move(value)
. Soluzione
Entrambi il codice è corretto e il 100% legale in C ++. C'è una differenza solo nel senso che nel primo caso viene spostato un riferimento (o meglio dire, in grado di essere spostato se viene utilizzata la destinazione appropriata) e in secondo caso, è la copia (vedi l'esempio seguente Chiarimento su questo) .
Nota che std::move
non sposta effettivamente l'oggetto. Elimina solo l'oggetto in un tipo di riferimento rvalue. Questo è tutto.
Si noti inoltre che in entrambi i casi , rvalueRef
è ancora un lvalue - un oggetto che ha un nome (cioè un identificatore da fare riferimento) non è mai un rvalo. Quindi, se non lo fai effettivamente spostarlo usando std::move
(o usando nuovamente il cast esplicito), allora non c'è alcuna differenza.
Ecco un esempio concreto:
//given function
std::string& GetReference();
std::string GetValue();
//target function
void f(std::string param);
.
E il tuo codice segue:
std::string& ref = GetReference();
std::string&& rvalueRef = std::move(ref);
std::string value = GetValue()
std::string&& rvalueCopy = std::move(value); //named changed
.
fino ad ora nessuna differenza affatto.
Ma se lo fai:
f(std::move(rvalueRef)); //actual object returned from GetReference is moved!
f(std::move(rvalueCopy)); //only a copy is moved.
.
L'oggetto effettivo viene spostato nel primo caso, e nel secondo caso, la copia viene spostata. Non fa alcuna differenza se lo fai:
f(std::move(GetReference())); //actual object returned from GetReference is moved!
f(std::move(GetValue())); //only a copy is moved.
.
Quindi vedi, nel tuo codice, non c'è differenza perché non c'è alcuna mossa effettiva a tutti . Il cast solo è lì. Per avere una mossa effettiva, dovrebbe esserci un tipo di destinazione appropriato che potrebbe invocare il costruttore di spostamento o il movimento-incarico! Nel tuo caso, non c'è invocazione di entrambi.
Altri suggerimenti
Q. è legale avere una ritenzione rvalue di un riferimento di lvalue?
Non è davvero la domanda che stai chiedendo.La domanda che stai davvero chiedendo è questa:
La risposta è sì.std::move
lancia semplicemente la sua discussione a un riferimento rvalue, che è sempre legale.La correttezza complessiva di ciò che stai facendo dipende da cosa fai quindi con il risultato di std::move
.Non c'è niente di sbagliato nel tuo codice di esempio.
q. C'è una differenza tra questi due casi?
// case 1 // case 2
Type& ref = GetReference(); Type value = GetValue();
f(std::move(ref)); f(std::move(value));
.
L'unica differenza è che nel caso 1, ref
è un riferimento all'oggetto restituito da GetReference()
, ma nella causa 2, value
è una copia dell'oggetto restituito da GetValue()
.