Forma sbagliata:
int &z = 12;
Forma corretta:
int y;
int &r = y;
Domanda :
perché il primo codice è sbagliato? Qual è il " significato " dell'errore nel titolo?
Forma sbagliata:
int &z = 12;
Forma corretta:
int y;
int &r = y;
Domanda :
perché il primo codice è sbagliato? Qual è il " significato " dell'errore nel titolo?
(ostringstream() << "x=" << x).str()
Risposte:
C ++ 03 3.10 / 1 dice: "Ogni espressione è un lvalue o un rvalue." È importante ricordare che la stima contro la stima è una proprietà delle espressioni, non degli oggetti.
Lvalues denomina oggetti che persistono oltre una singola espressione. Ad esempio, obj
, *ptr
, ptr[index]
, e ++x
sono tutti lvalue.
I valori sono provvisori che evaporano alla fine della piena espressione in cui vivono ("al punto e virgola"). Ad esempio, 1729
, x + y
, std::string("meow")
, e x++
sono tutti rvalues.
L'operatore address-of richiede che il suo "operando sia un lvalue". se potessimo prendere l'indirizzo di un'espressione, l'espressione è un lvalue, altrimenti è un rvalue.
&obj; // valid
&12; //invalid
int & = 12;
non è valido, lo standard dice che una stringa letterale è un lvalue, altri letterali sono rvalue.
std::string("meow")
costruisce un oggetto di tipo std::string
e restituisce un rvalue che designa questo oggetto, 1729
non ha effetti collaterali e restituisce un valore 1729 come valore di tipo int
.
"Lvalues name objects that persist beyond a single expression."
è corretta al 100%. Al contrario, il tuo esempio (const int &)1
non è corretto, perché NON è un oggetto "con nome".
int &z = 12;
Sul lato destro, un oggetto temporaneo di tipo int
viene creato dall'integrale letterale 12
, ma il temporaneo non può essere associato a un riferimento non const. Da qui l'errore. È lo stesso di:
int &z = int(12); //still same error
Perché viene creato un temporaneo? Poiché un riferimento deve fare riferimento a un oggetto nella memoria e affinché un oggetto esista, deve essere prima creato. Poiché l'oggetto è senza nome, è un oggetto temporaneo . Non ha nome. Da questa spiegazione, è diventato abbastanza chiaro perché il secondo caso va bene.
Un oggetto temporaneo può essere associato al riferimento const, il che significa che puoi farlo:
const int &z = 12; //ok
Per ragioni di completezza, vorrei aggiungere che C ++ 11 ha introdotto rvalue-reference, che può legarsi a un oggetto temporaneo. Quindi in C ++ 11, puoi scrivere questo:
int && z = 12; //C+11 only
Nota che c'è &&
intead di &
. Si noti inoltre che const
non è più necessario, anche se l'oggetto a cui si z
lega è un oggetto temporaneo creato dall'integrale letterale 12
.
Poiché C ++ 11 ha introdotto rvalue-reference , int&
è ora chiamato lvalue-reference .
12
è una costante del tempo di compilazione che non può essere modificata a differenza dei dati a cui fa riferimento int&
. Quello che puoi fare è
const int& z = 12;
void f( vector<int> const & )
, idiomatica per passare un vettore che non deve essere modificato. Il problema ora è che non f( vector<int>(5) )
sarebbe corretto e l'utente dovrebbe fornire un sovraccarico diverso, il void f( vector<int> v ) { f(v); }
che è banale.
f( vector<int>(5) )
, il compilatore crea un temporaneo e quindi lega il riferimento a quello temporaneo, e allo stesso modo se c'era una conversione implicita da 5
direttamente. Ciò consente al compilatore di generare una singola firma per la funzione e consente l'implementazione della funzione da parte di un singolo utente. Da lì in poi, un comportamento simile viene definito per il resto degli usi di riferimenti costanti per coerenza.
T const & r = *ptr;
qualsiasi uso successivo di r
nella funzione può essere sostituito da *ptr
, e r
non deve esistere in fase di esecuzione) oppure potrebbe dover essere implementato mantenendo l'indirizzo dell'oggetto che alias (considera di memorizzare un riferimento come membro di un oggetto) - che è implementato come un puntatore con riferimento automatico.
Queste sono le regole del linguaggio C ++:
12
) è un "rvalue"int &ri = 12;
è mal formatoDevi capire che queste sono regole C ++. Lo sono e basta.
È facile inventare un linguaggio diverso, diciamo C ++ ', con regole leggermente diverse. In C ++ ', sarebbe consentito creare un riferimento non const con un rvalue. Non c'è niente di incoerente o impossibile qui.
Ma consentirebbe un codice rischioso in cui il programmatore potrebbe non ottenere ciò che intendeva, ei progettisti C ++ hanno giustamente deciso di evitare quel rischio.
I riferimenti sono "puntatori nascosti" (non nulli) a cose che possono cambiare (lvalues). Non puoi definirli come una costante. Dovrebbe essere una cosa "variabile".
MODIFICARE::
Sto pensando a
int &x = y;
quasi equivalente a
int* __px = &y;
#define x (*__px)
dove __px
è un nuovo nome, e #define x
funziona solo all'interno del blocco contenente la dichiarazione di x
riferimento.
const
:)
const