Costruttore di copia

di il
20 risposte

Costruttore di copia

Buongiorno,

sto cercando di approfondire il costruttore di copia, ma c'è qualcosa che non ho capito.
Ho fatto una classe Prova in cui ho ridefinito il costruttore di copia, e in questa classe ho definito una funzione torna() che restituisce la classe stessa:

Prova torna() {
return *this;
}

Ora, se istanzio un oggetto di tipo Prova:

Prova prova;

e poi da questo oggetto chiamo la funzione trova:

prova.trova();

succede che viene chiamato il costruttore di copia, dato che trova ritorna la classe stessa. Ho quindi scritto la seguente istruzione:

Prova pr = prova.torna();

aspettandomi due chiamate al costruttore di copia: la prima per il ritorno di torna e la seconda per inizializzare pr. Questo non succede, c'è anche qui una sola chiamata, e non capisco perché. Come viene inizializzato l'oggetto pr?
Grazie

20 Risposte

  • Re: Costruttore di copia

    Nessuno ha riscontrato lo stesso comportamento?
  • Re: Costruttore di copia

    Non ho capito il problema ...

    Il costruttore di copia viene chiamato perché viene restituito un oggetto (*this) ... perché dovrebbe essere chiamato due volte?
  • Re: Costruttore di copia

    oregon ha scritto:


    Non ho capito il problema ...

    Il costruttore di copia viene chiamato perché viene restituito un oggetto (*this) ... perché dovrebbe essere chiamato due volte?
    Una volta per restituire l'oggetto (*this), e una volta per inizializzare l'oggetto pr.
  • Re: Costruttore di copia

    No, viene chiamato una sola volta per copiare l'oggetto (*this) in pr..
  • Re: Costruttore di copia

    Il compilatore non e' proprio stupido
    Ha ottimizzato!
  • Re: Costruttore di copia

    Perché dovrebbe essere chiamato per inizializzare pr ?
  • Re: Costruttore di copia

    oregon ha scritto:


    Perché dovrebbe essere chiamato per inizializzare pr ?
    Perché l'inizializzazione di un oggetto è fatta o col costruttore o col costruttore di copia. Se faccio:

    Prova pr1; // l'inizializzazione è fatta col costruttore di default;
    Prova pr2 = pr1; // l'inizializzazione è fatta col costruttore di copia
  • Re: Costruttore di copia

    migliorabile ha scritto:


    Il compilatore non e' proprio stupido
    Ha ottimizzato!
    Ah ok, è che non mi quadrava perché sono andato a vedere in debug e le istruzioni assembler eseguite sono le stesse, nel senso che quando faccio:
    Prova pr = prova. torna();
    vengono eseguite le stesse istruzioni assembler, non una in più, di quando faccio:
    prova.torna();
    Questa cosa continuo a non capirla.
  • Re: Costruttore di copia

    Il costruttore di copia viene richiamato quando esegui la

    torna

    La copia avviene in un [oggetto temporaneo] nello stack (in tutti e due i casi) ma solo nel secondo l'oggetto temporaneo viene copiato nell'oggetto a sinistra dell' =
  • Re: Costruttore di copia

    Se controlli il distruttore, infatti, ti accorgi che anche nel caso di una semplice

    prova.trova();

    questo viene chiamato per distruggere l'oggetto temporaneo.
  • Re: Costruttore di copia

    oregon ha scritto:


    Il costruttore di copia viene richiamato quando esegui la

    torna

    La copia avviene in un [oggetto temporaneo] nello stack (in tutti e due i casi) ma solo nel secondo l'oggetto temporaneo viene copiato nell'oggetto a sinistra dell' =
    Grazie mille, mi hai dato la risposta che cercavo! Infatti un altro interrogativo era come fosse possibile fare una cosa del genere:

    prova.torna().torna();

    Mi chiedevo da quale oggetto fosse chiamata torna() la seconda volta, se il ritorno della prima chiamata a torna() non veniva salvato in nessun oggetto. Quindi, da quello che dici, deduco che la seconda chiamata di torna() venga fatta dall'oggetto temporaneo, il quale viene distrutto dopo la seconda chiamata di torna().
    Mi rimane però il dubbio su chi faccia la copia in pr nell'istruzione:
    Prova pr = prova.torna();
    Non dovrebbe essere il costruttore di copia?
  • Re: Costruttore di copia

    In questo caso

    prova.torna().torna();

    vengono creati due oggetti temporanei che vengono distrutti in sequenza al ritorno.

    Orientativamente, equivale a

    Prova temp1 = prova.torna();
    Prova temp2 = temp1.torna();
    (distruggi temp2)
    (distruggi temp1)
    chi faccia la copia in pr ...
    La copia la fa proprio il costruttore di copia ...
  • Re: Costruttore di copia

    oregon ha scritto:


    chi faccia la copia in pr ...
    La copia la fa proprio il costruttore di copia ...
    Forse ho capito: detto molto grezzamente e imprecisamente, il costruttore di copia mette l'oggetto temporaneo all'indirizzo di pr, quindi l'oggetto non è temporaneo e non viene distrutto. Ho capito bene? Se è così, è normale che il costruttore di copia non venga chiamato due volte, perché l'unica differenza fra le due operazioni è dove sistemare nello stack l'oggetto creato.
  • Re: Costruttore di copia

    Quasi ... avviene questo

    1) alla funzione torna viene passato l'indirizzo dell'oggetto pr e l'indirizzo dell'oggetto prova

    2) nella funzione torna viene chiamato il costruttore di copia che copia (tramite i puntatori ricevuti) il contenuto dell'oggetto prova nell'oggetto pr

    Se chiami solo la funzione torna, avviene

    1) alla funzione torna viene passato l'indirizzo di un oggetto temporaneo e dell'oggetto prova

    2) nella funzione torna viene chiamato il costruttore di copia che copia (tramite i puntatori ricevuti) il contenuto dell'oggetto prova nell'oggetto temporaneo

    3) l'oggetto temporaneo viene distrutto
Devi accedere o registrarti per scrivere nel forum
20 risposte