2013-06-28 9 views
6

Mentre stavo leggendo http://thbecker.net/articles/rvalue_references/section_01.html, ho seguito snippiest.Differenza esatta tra rvalue e lvalue

// lvalues: 
// 
int i = 42; 
i = 43; // ok, i is an lvalue 
int& foo(); 
foo() = 42; // ok, foo() is an lvalue 
int* p1 = &foo(); // ok, foo() is an lvalue 

// rvalues: 
// 
int foobar(); 
int j = 0; 
j = foobar(); // ok, foobar() is an rvalue 
int* p2 = &foobar(); // error, cannot take the address of an rvalue 
j = 42; // ok, 42 is an rvalue 

Perché p2 int * = & foobar(); è una dichiarazione di errore, mentre int * p1 = & foo(); non è un errore Quanto più tardi uno è lvalue mentre il primo è valore?

Grazie in anticipo

+0

Credo che la tua ultima frase abbia arretrato –

risposta

4

Così hanno due funzioni:

int& foo(); 
int foobar(); 
  • foo è una funzione che restituisce lvalue riferimento a int
  • foobar è una funzione che restituisce int

Le espressioni di chiamata di funzione:

foobar() 
foo() 

entrambi hanno tipo int (i riferimenti vengono rimossi dalle espressioni, in modo foo() è di tipo int e non lvalue-reference to int). Le due espressioni sono diverse categorie di valori:

  • foobar() è un prvalue (una chiamata di funzione per una funzione che restituisce un non-reference è un prvalue)
  • foo() è un lvalue (una chiamata di funzione per una funzione che restituisce un lvalue-riferimento è un lvalue)

non si può prendere l'indirizzo di un rvalue (un prvalue è una sorta di rvalue), in modo da &foobar() non è permesso.

È possibile prendere l'indirizzo di un lvalue in modo che &foo() sia consentito.

+0

Perché non è possibile prendere l'indirizzo di foo? –

+0

@ ss7don: intendi l'espressione 'foo()'? Puoi prendere l'indirizzo di 'foo()'. Leggi l'ultima riga della mia risposta di nuovo. –

+0

Ho accettato la risposta poiché sembra ragionevole. Francamente non riesco ancora a capire la differenza esatta tra foo e foobar. Entrambe sono funzioni. Ma come uno è valore e un altro è lvalue. –

6

Supponiamo di avere il codice di esempio mostrato di seguito in C. Compilerà? Come funzionano i concetti di lvalue e rvalues ​​in questo problema?

#define X 8 
int main(void) 
{ 
    ++X; // will this line compile? 
     return 0; 

} 

Il concetto di lvalue e rvalues ​​deve essere spiegato un po 'per capire davvero il codice di cui sopra, e il problema viene chiesto. Prima di procedere, è necessario notare che la definizione di lvalues ​​e rvalues ​​qui presentati non è esatta, in quanto anche gli standard C stessi sono piuttosto vaghi sulla definizione.

La differenza tra rvalues ​​e lvalue

Un oggetto è una regione di memoria che può essere esaminato, ma non necessariamente modificato. Un lvalue è un'espressione che si riferisce a un tale oggetto. Il termine lvalue si riferiva originariamente agli oggetti che appaiono a sinistra (da cui il lato "l") di un'espressione. Quella definizione non si applica più poiché qualsiasi tipo const-qualified è considerato anche un lvalue, ma non può mai apparire sul lato sinistro di un'istruzione di assegnazione perché non può essere modificato. Quindi, il termine "lvalue modificabile" è stato creato per fare riferimento a un lvalue che può essere modificato e un tipo const-qualificato non rientra in questa categoria.

Un rvalue è qualsiasi espressione che ha un valore, ma non può avere un valore assegnato ad esso. Si potrebbe anche dire che un rvalue è qualsiasi espressione che non sia un lvalue.Un esempio di un valore di rvalore sarebbe una costante letterale - qualcosa come "8" o "3,14". Quindi, chiaramente il valore '8' nel codice sopra è un valore.

Utilizzando la nostra comprensione di lvalue e rvalues ​​per rispondere alla domanda

Ora proviamo a risolvere il problema. A rigor di termini, l'operando dell'operatore di incremento prefisso (o suffisso) deve essere un lvalue modificabile. Quindi, qual è l'operando dell'operatore di incremento del prefisso nel nostro codice sopra?

Poiché X è una macro, l'istruzione sopra verrà estesa a "++ 8" dopo l'esecuzione del preprocessore. Ciò significa che "8" è l'operando dell'operatore di incremento del prefisso. E poiché 8 è un valore non può essere usato come argomento per "++". Questo, a sua volta, significa che il codice sopra non verrà compilato.

+1

Molto bello, ma perché preoccuparsi di questo esempio? Non vedo come la domanda del quiz possa aiutare a capire questo problema. – SChepurin