La differenza è che ++a
è un lvalue, tuttavia non lo è a++
. Questo è specificato da C++ 14 [expr.pre.incr]/1:
L'operando prefix ++
è modificato aggiungendo 1 [...] La operando è un valore assegnabile modificabili. [...] Il risultato è l'operando aggiornato; si tratta di un lvalue
e [expr.post.incr]/1:
[...] Il risultato è un prvalue.
Ora consideriamo auto && b = ++a;
. ++a
è un lvalue. auto&&
è un riferimento di inoltro. I riferimenti di inoltro possono effettivamente associarsi a lvalue: lo auto
può dedurre esso stesso un tipo di riferimento. Questo codice si riduce a int &b = ++a;
.
Quando un riferimento è associato a un lvalue dello stesso tipo, il riferimento si collega direttamente, quindi b
diventa un altro nome per a
.
Nel secondo esempio, auto && b = a++;
, a++
è un prvalue. Ciò significa che non ha un indirizzo associato e non ha più alcuna relazione con la variabile a
. Questa riga ha lo stesso comportamento di ++a; auto && b = (a + 0);
.
In primo luogo, poiché a++
è un valore di prua, auto&&
viene dedotto a int&&
. (Ad esempio, auto
deduce a int
). Quando un riferimento di tipo non di classe è associato a un valore di provalutazione, un oggetto temporaneo viene inizializzato dalla copia dal valore. Questo oggetto ha una durata estesa per corrispondere al riferimento.
Così b
nel secondo caso si associa a un oggetto diverso da a
, un int "temporaneo" (che non è così temporaneo, poiché dura finché b
fa).
Le regole di collegamento di riferimento sono in [dcl.init.ref].
fonte
2016-02-10 13:10:51
Ti darò un suggerimento - "a" non è un valore. – erip
@erip Sì, lo so, ma quale è la differenza in due esempi per 'b'? – vladon
Nel secondo esempio, 'b' ottiene il valore di' a' senza incrementarlo prima, come nel primo esempio. – x13