Ti riporto un mio vecchio post:
Non devi confondere l'operatore & usato per avere l'indirizzo di una variabile e l'operatore & usato per dichiarere un reference.
Se dichiari
1 - void f(Classe *a)
stai dicendo che f prende un puntatore ad un oggetto di tipo Classe ai cui membri puoi accederte con ->, e per invocare f scrivi:
f(&oggetto);
Se scrivi
2 - void f(Class &a)
f prende un reference all'oggetto 'a', e la funzione va invocata come
//senza & rispetto aprima
f(nomeoggetto);
Un reference puoi considerarlo come un alias, cioè un altro modo di chiamare l'oggetto 'a'. L'argomento 'a' puo essere MODIFICATO permanentemente dalla funzione, ad esempio con un'istruzione del tipo:
a.nome_campo = 0;
la variabile argomento viene modificata e la modifica rimane all'uscita della funzione.
Usando il referrence puoi accedere ai membri dell'oggetto argomento senza usare ->, ma usando il punto. La stessa cosa la puoi fare se dichiari
3 - void f(Class a)
in cui non passi il reference, ma proprio l'oggetto; la grande differenza tra la dichiarazione 2) e la dichiarazione 3) sta nel fatto che nella 3) l'argomento viene passato per valore, cioè viene effettuata una copia dell'argomento, e la funzione opera sulla copia, non sulla variabile originale. Se modifichi l'argomento, all'uscita della funzione le modifiche sono perse proprio perche avvengono sulla copia locale della funzione. Per poter modificare direttamente l'argomento in C non avevi altra scelta che passare il puntatore alla variabile, come nella dichiarazione 1); in C++ sono stati intreodotti i reference con cui puoi passare proprio l'oggetto, e non una sua copia, e in piu puoi accedere ai suoi campi con il punto anzicche con la freccia ->.
Riassumendo:
1 - Passaggio per Puntatore
......dichiarazione: void f(NomeClasse *a);
......invocazione: f(&oggetto);
......Modifico l'argomento: SI
......Accesso ai membri con: ->
2 - Passaggio per Reference
......dichiarazione: void f(NomeClasse &a);
......invocazione: f(oggetto);
......Modifico l'argomento: SI
......Accesso ai membri con: .
3 - Passaggio per Valore
......dichiarazione: void f(NomeClasse a);
......invocazione: f(oggetto);
......Modifico l'argomento: NO
......Accesso ai membri con: .
se ad esempio la classe dell'oggetto 'a' ha un campo pubblico nome_campo puoi modificarlo con
a.nome_campo = 0;
però se l'oggetto 'a' non è passato per reference, ma per valore, stai modificando una copia dell'oggetto, esempio:
Codice PHP:
#include <iostream>
using namespace std;
class MiaClasse{
public:
int nome_campo;
MiaClasse(){
nome_campo = 1;
}
};
//Passaggio per valore
void f1(MiaClasse a){
a.nome_campo = 0;
}
void f2(MiaClasse &a){
a.nome_campo = 0;
}
int main(){
MiaClasse a;
cout << "a.nome_campo dopo la creazione: " << a.nome_campo << endl;
f1(a);
cout << "a.nome_campo dopo f1(a): " << a.nome_campo << endl;
f2(a);
cout << "a.nome_campo dopo f2(a): " << a.nome_campo;
return 0;
}
l'ouput che ottieni è:
Codice PHP:
a.nome_campo dopo la creazione: 1
a.nome_campo dopo f1(a): 1
a.nome_campo dopo f2(a): 0