Passaggio indirizzo funzione

di dna_programmer il
9 risposte
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

  • 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.
  • 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
  • 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.
  • 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
  • Non ci sono errori in quel codice (a meno di non copiarlo così comè e tentare di compilarlo).
  • 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
  • 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.
  • 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ò?
  • 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