Passaggio indirizzo funzione

di il
9 risposte

Passaggio indirizzo funzione

Salve a tutti, io ho questa funzione

void prova(int &a)
{
    cout<<&a<<endl;  //esempio
}

com'è che nel main devo fare così:

int main()
{
  int*p=new int;

  prova(*p); //perchè devo fare così'  e non

  prova(p); //cosi ?

return 0;
}
cioè devo passare l'indirizzo di una variabile intera, quindi avendo un puntatore a intero, passando
p, si passa il contenuto del puntatore(quindi l'indirizzo della variabile puntata);

mentre se passo *p, passo il contenuto della variabile puntata
mentre io voglio passare l'indirizzo.

com'è questa cosa?

9 Risposte

  • Re: Passaggio indirizzo funzione

    Nel prototipo di prova stai passando un reference a un intero, non il puntatore; motivo per cui devi usare *p e non p affinché il codice compili.
    Il prototipo corretto è:
    void prova(int *a)
    l'ampersand ( & ) assume significato diverso se posto nel prototipo di funzione.
  • Re: Passaggio indirizzo funzione

    Non ho capito una cosa però, cioé se devo passare l'indirizzo della variabile puntata , l'indirizzo é contenuto in p, mentre se passo *p passo il contenuto della variabile puntata, quindi se p punta a una variabile x che vale 4 , in realtá passo il 4 , questo passaggio non riesco a capirlo
  • Re: Passaggio indirizzo funzione

    Storicamente i reference nascono per consentire l'overload degli operatori (ad esempio l'operatore +).
    Li puoi pensare come a dei puntatori "mascherati" dal compilatore (detti alias).
    Se scrivi:
    
    void prova(int &a)
    {
        cout<<&a<<endl;  //esempio
    }
    ...
    
    int p = 4;
    prova(p);
    
    
    puoi pensare che il compilatore trasformi per te il codice in questo modo (non è detto che lo faccia davvero, ma è per farti capire il principio).
    
    void prova(int *a)
    {
        cout<<&(*a)<<endl;  //esempio
    }
    ...
    
    int p = 4;
    prova(&p);
    
    Nel primo caso è il compilatore che effettua i vari passaggi, nel secondo (se lo scrivi apposta tu), sei tu che devi esplicitare i vari passaggi.

    Il reference è un sinomino: all'interno di prova() la variabile a è sinonimo della variabile esterna p.
  • Re: Passaggio indirizzo funzione

    Si ma se io faccio così':
    
    void prova(int &a)
    {
        cout<<&a<<endl;  //esempio
    }
    ...
    
    int p = 4;
    prova(p);
    
    
    il compilatore mi da errore sull'ultima riga, non è che me lo sostituisce lui
  • Re: Passaggio indirizzo funzione

    Non ci sono errori in quel codice (a meno di non copiarlo così comè e tentare di compilarlo).
  • Re: Passaggio indirizzo funzione

    A si mi ero sbagliato io.ok tutto funziona.

    Io , però,ancora non ho capito il mio dubbio principale e cioè:
    quando ad una funzione devo passare un reference, perché nel caso io abbia un puntatore "p", gli devo passare "*p" e non "p" ?
    Scusami sarò anche ottuso ma non riesco a capire la motivazione.Grazie ancora per la disponibilità e pazienza
  • Re: Passaggio indirizzo funzione

    Dipende dal prototipo della funzione.
    Se la funzione richiede un puntatore, gli passi un puntatore;
    se richiede un reference gli passi la variabile così com'è.
    Se crei (o hai) un puntatore, ma la funzione richiede un reference, prima di usare quella funzione devi prima dereferenziare il puntatore altrimenti hai errore.

    Leggendo da destra a sinistra entrambe le dichiarazioni, nel primo caso hai:
    a è un reference a int --> si deve passare un int
    nel secondo caso
    a è un puntatore a int --> si deve passare un puntatore a int.

    E' come tentare di aprire una porta: se non hai la chiave giusta non combini nulla.
  • Re: Passaggio indirizzo funzione

    A ok quindi se la funzione richiede un reference , gli devo passare il puntatore ma deve dereferenziare il puntatore (*p).

    Quindi c'è un motivo sintattico oppure c'è una motivazione più seria alle spalle di tutto ciò?
  • Re: Passaggio indirizzo funzione

    I reference sono stati introdotti per consentire l'overload degli operatori nelle classi.
    Se hai (pseudo codice):
    
    struct A {
       int var;
       A operator + (const A& rhs) { 
           A a;
           a.var = var + rhs.var;
           return A;
       }
    };
    ...
    A x,y,z;
    z = x + y;  // qui viene invocato l'operatore + della classe.
      
    A* px = &x;
    A* py = &y;
    A* pz = &z;
    
    pz = px + py; // qui non viene invocato l'operatore + della classe, ma sommati gli indirizzi dei puntatori.
    
    *pz = *px + *py; // dereferenziando i puntatori si ottengono gli oggetti, quindi viene invocato l'operatore + della classe.
    

    Da qui all'adozione su vasta scala dei reference il passo è breve, anche perché consentono una maggiore pulizia sintattica.
    (Lo stesso motivo per cui scriveresti px->var al posto di (*px).var ).
Devi accedere o registrarti per scrivere nel forum
9 risposte