Rvalue Ritenence of Lvalue Reference vs Rvalue Riferimento di lvalue / rvalue

StackOverflow https://stackoverflow.com//questions/23013120

  •  21-12-2019
  •  | 
  •  

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)
.

È stato utile?

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:

q. è legale lanciare un riferimento lvalue a un riferimento rvalue?

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().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top