PDA

Visualizza la versione completa : [C++] Puntatori & Reference


cagnaluia
24-08-2005, 15:20
Qualche delucidazione:


esempio:

[code]
void f(int* x) { (*x)++; }
void g(int& x) { x++; }

main(void) {
int a=0;
f(&a);
g(a);
}


come si legge questo? per capire cosa accade nel main e cosa raccoglie/usano le funzioni?

cagnaluia
24-08-2005, 15:30
sul main io leggo che ad f viene passato l'indirizzo di a.
che a g viene passato a. (ma.....)

poi..

la funzione f raccoglie il puntatore a x ??
e la g raccoglie l'indirizzo di x ??

anx721
24-08-2005, 15:38
che intendi per raccogliere?

la f riceve un puntatore ad un intero e quindi è in grado di modificare l'intero con istruzioni del tipo:

*x = 10;


all'uscita della f x avrà il valore 10. Se non passi il puntatore ma passi un int

int f(int x){x = 10}

all'uscita da f x avrà il vecchioo valore che aveva prima.

Quindi per modificare una variabile o un oggetto devi passarne il puntatore e accedere all'oggetto con la sintassi: *x

Le reference permettono di passare il puntatore senza pero dover usare al sintassi *x:

viud g(int &x){x = 10}

all'uscita da g x avrà il valore 10

anx721
24-08-2005, 15:40
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:



#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 è:



a.nome_campo dopo la creazione: 1
a.nome_campo dopo f1(a): 1
a.nome_campo dopo f2(a): 0

cagnaluia
24-08-2005, 15:54
grazie, sto trascrivendo :)

Loading