A const
il riferimento di lvalue può essere associato a qualsiasi cosa. Un riferimento di rvalue può essere associato solo ai valori non const
.
non-const lvalue const lvalue non-const rvalue const rvalue
const T& yes yes yes yes
T&& no no yes no
Come potete vedere, sono molto diversi.
Inoltre, se una chiamata di funzione restituisce un riferimento lvalue, tale espressione è un lvalue, ma se una chiamata di funzione restituisce un riferimento rvalore all'oggetto, tale espressione è un valore x.
Una chiamata di funzione è un lvalue se il tipo risultato è un tipo di riferimento lvalue o un riferimento rvalue al tipo di funzione, un xValue se il tipo di risultato è un riferimento rvalue al tipo di oggetto, ed una prvalue altrimenti.
Per quanto riguarda quando si desidera modificare un valore rvalore - beh, questo è esattamente ciò di cui si muovono le semantiche. Si consideri il seguente chiamata di funzione:
void func(std::string);
func(std::string("Hello"));
L'espressione std::string("Hello")
è un rvalue che crea un oggetto temporaneo. Quando si inizializza il parametro std::string
con questo valore, sceglierà il costruttore che prende un riferimento di rvalue - il costruttore di spostamento . Questo costruttore quindi ruba le cose dal valore rvalue, che è in genere molto più veloce di una copia completa. Siamo in grado di rubare perché noi conosciamo è temporaneo.
Per quanto riguarda quando si dovrebbe tornare const
riferimenti lvalue o riferimenti rvalue:
che restituisce un riferimento lvalue const
è più comunemente usato quando si vuole dare l'accesso per leggere un oggetto "interna" (forse un membro di una classe), ma non consentire alle persone di modificarlo.
Il ritorno di un riferimento di valore massimo è più comunemente utilizzato (non comune affatto) quando si desidera consentire al codice chiamante di spostarsi da un oggetto "interno" (forse un membro di una classe). Quindi, invece di spostarsi da un oggetto restituito temporaneo (come farebbero quando si restituisce un valore), si spostano letteralmente dall'oggetto interno.
Questo può essere ottenuto anche con un riferimento di lvalue non- const
, ma in tal caso dovrebbero esplicitamente lo std::move
.
Quindi non è molto probabile che sia necessario restituire un riferimento di rvalue.
Non che std::forward
abbia un tipo restituito simile a T&&
. Tuttavia, questo è ingannevole, perché potrebbe essere o meno un riferimento di rvalue a seconda del tipo di T
. Vedi universal references.
Giusto, stavo indovinando così. Modificherò il post ... – jbgs
Se stai parlando di ** return ** allora probabilmente non vuoi restituire un * rvalue-references *. Mentre potrebbe esserci qualche caso d'uso che potrebbe essere implementato restituendo un * rvalue-reference *, nella maggior parte delle situazioni causerà un comportamento indefinito. –