2012-02-15 10 views
40

Ho letto ovunque che un riferimento deve essere inizializzato allora e lì e non può essere nuovamente inizializzato di nuovo.Possiamo riassegnare il riferimento in C++?

Per testare la mia comprensione, ho scritto il seguente piccolo programma. Sembra come se in realtà sono riuscito a riassegnare un riferimento. Qualcuno può spiegarmi cosa sta succedendo nel mio programma?

#include <iostream> 
#include <stdio.h> 
#include <conio.h> 

using namespace std; 

int main() 
{ 
    int i = 5, j = 9; 

    int &ri = i; 
    cout << " ri is : " << ri <<"\n"; 

    i = 10; 
    cout << " ri is : " << ri << "\n"; 

    ri = j; // >>> Is this not reassigning the reference? <<< 
    cout << " ri is : " << ri <<"\n"; 

    getch(); 
    return 0; 
} 

Il codice compila bene e l'uscita è come mi aspetto:

ri is : 5 
ri is : 10 
ri is : 9 

risposta

42

ri = j; // >>> Is this not reassigning the reference? <<<

No, ri è ancora un riferimento alla i - si può dimostrare questo stampando &ri e &i e vedere che sono lo stesso indirizzo.

Quello che hai fatto è modificare itramite il riferimento ri. Stampa i dopo, e vedrai questo.

Inoltre, per confronto, se si crea un const int &cri = i; non sarà possibile assegnarlo a tale.

+0

Perché 'const int & cri = i' non è consentito? Su quale linea non puoi scriverlo? Perché per me il compilatore permette di inserire tale linea in qualsiasi posto. A parte questo, è una risposta chiara e concisa! – mercury0114

+0

Non ho detto che non è permesso - come hai osservato, prendere un riferimento const a una variabile non const va bene. L'ho detto che non ti ho permesso di assegnarlo a quel_, il che significa che non puoi cambiare la variabile originale tramite un const ref, come OP ha fatto con 'ri'. – Useless

+0

Oh, giusto, ora capisco cosa intendevi. – mercury0114

3

Quando si assegna qualcosa ad un riferimento effettivamente assegnare il valore per l'oggetto il riferimento è destinata a. Quindi questo:

ri=j; 

ha lo stesso effetto di

i = j; 

avrebbe perché ri è destinato a i. Quindi qualsiasi azione su ri viene eseguita su i.

3

Non si sta riassegnando il riferimento quando si esegue ri = j;. Stai attualmente assegnando j a i. Prova a stampare i dopo la linea e vedrai che i ha cambiato valore.

6

Sembra che in realtà sia riuscito a riassegnare un riferimento. È vero?

No, non è così. In effetti stai riassegnando il valore e non stai riconciliando il riferimento.

Nell'esempio, quando si esegue int &ri = i;, ri è associato a i per la sua durata. Quando si esegue ri = j;, si assegna semplicemente il valore di j a ri. ri rimane ancora un riferimento a i! E il risultato e 'lo stesso risultato come se si fosse invece scritto i = j;

Se si capisce puntatori bene, poi sempre pensare di riferimento come interpretazione analogica di T* const dove T è qualsiasi tipo.

0

L'OP ha chiesto di modificare l'oggetto di riferimento tramite l'assegnazione al riferimento ed è stato detto molto correttamente che questo ha cambiato l'oggetto di riferimento, non il riferimento. Ora ho fatto un tentativo più intenso di cambiare davvero il riferimento e ho trovato cose potenzialmente sgradevoli. Prima il codice. Tenta di riassegnare alla variabile di riferimento un oggetto appena creato, quindi altera l'oggetto referenziato di riferimento, trova che questo non si riflette negli oggetti apparentemente referenziati e conclude che potremmo avere un caso di puntatore pendente in C++. Ci scusiamo per il codice composto frettolosamente.

using namespace std; 
vector<int>myints; 

auto &i = myints.emplace_back(); // allocate and reference new int in vector 
auto myintsaddr = &myints; auto myintfrontaddr = &myints.front(); // for future reference 
i = 1;        // assign a value to the new int through reference 
cout << hex << "address of i: 0x" << &i << " equals " << "address of 
myints.back(): 0x" << &myints.back() << '.' << endl; // check reference as expected 
i = myints.emplace_back();  // allocate new int in vector and assign to old reference variable 
i = 2;       // give another value to i 
cout << "i=" << i << ", myints={" << myints[0] << ", "<< myints[1] << '}' << endl; // any change to potentially referenced objects? 
cout << hex << "&i: 0x" << &i << " unequal to " << "&myints.back(): 0x" << &myints.back() << " as well as &myints.front(): 0x" << &myints.front() << endl; 
cout << "Myints " << (myintsaddr== &myints?"not ":"") << "relocated from " << myintsaddr << " to " << &myints << endl; 
cout << "Myints front() " << (myintfrontaddr == &myints.front() ? "not " : "") << "relocated from " << myintfrontaddr << " to " << &myints.front() << endl; 

uscita:

address of i: 0x0063C1A0 equals address of myints.back(): 0x0063C1A0. 
i=2, myints={1, 0} 
&i: 0x0063C1A0 unequal to &myints.back(): 0x0063F00C as well as &myints.front(): 0x0063F008 
Myints not relocated from 0039FE48 to 0039FE48 
Myints front() relocated from 0063C1A0 to 0063F008 

Conclusione: almeno nel mio caso (VS2017) il riferimento ha mantenuto l'esatto stesso indirizzo in memoria, ma sono stati riassegnati i valori di riferimento (parte del vettore) altrove. Il riferimento potrebbe essere penzolante.

Problemi correlati