2013-03-28 21 views
7

Se non sbaglio, penso che sia un riferimento const sia un riferimento rval possono essere associati a un valore. C'è qualche differenza pratica tra una funzione che restituisce il primo e una funzione che restituisce il secondo?Differenza tra il ritorno di un riferimento const e il riferimento del valore di riferimento

MODIFICA. Non posso modificare il primo, ma perché dovrei essere interessato a modificare un valore? Ha senso?

+0

Giusto, stavo indovinando così. Modificherò il post ... – jbgs

+2

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

risposta

16

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.

+0

Nota a margine: direi che è piuttosto raro che un programma produca valori costanti. – Angew

+0

Grazie. Ma c'è qualche caso pratico in cui ho bisogno di restituire un riferimento di rvalue? – jbgs

+0

OK, se ho capito bene, restituire un riferimento di rval ha senso quando sto passando questo riferimento restituito a un'altra funzione che è destinata a "rubare" l'oggetto. – jbgs

1

C'è qualche differenza pratica tra una funzione che restituisce il primo e una funzione che restituisce il secondo?

La domanda sembra essere mal formata. Una funzione che restituisce una costante Ivalue riferimento fornisce accesso a un oggetto solo per lettura, mentre una funzione che restituisce un rvalue riferimento fornisce l'accesso per spostamento che significa che il chiamante può prendere il contenuto del oggetto di riferimento e spostare in un oggetto diverso. Non sono paragonabili in alcun modo.

In entrambi i casi, i riferimenti devono puntare a un oggetto la cui durata si estende oltre la fine della funzione che lo restituisce, altrimenti il ​​chiamante eseguirà un controllo con comportamento non definito sull'utilizzo di tale riferimento.

Problemi correlati