Autodidatta ha scritto:
Ho scritto questo semplice programmino per capire il meccanismo del costruttore di copia
class Prova;
void funz(Prova p) {}
int main(int argc, char* argv[]) {
Prova p1;
Prova p3 = p1;
funz(p1);
Prova p5 = Prova();
funz(Prova());
return 0;
}
ma ci sono alcuni aspetti che non sono riuscito a chiarire.
Col debug ho notato che:
1) eseguendo l'istruzione Prova p1;
viene giustamente chiamato il costruttore normale, e non quello di copia
2) eseguendo Prova p3 = p1;
viene giustamente chiamato il costruttore di copia, e non quello normale
3) eseguendo funz(p1);
viene giustamente chiamato il costruttore di copia, e non quello normale
4) eseguendo Prova p5 = Prova();
viene giustamente chiamato il costruttore normale, ma non capisco perché non venga chiamato anche quello di copia
5) eseguendo funz(Prova());
viene giustamente chiamato il costruttore normale, ma non capisco perché non venga chiamato anche quello di copia
Negli ultimi due casi il costruttore normale non dovrebbe costruire un oggetto temporaneo che poi il costruttore di copia copierà rispettivamente in p5 e nell'argomento della funzione p?
Grazie
calma calma, vedendo il codice della tua classe:
1) esatto, viene chiamato il costruttore di default
2) errore! viene chiamato l'overloading dell'operatore = (che esisterebbe anche se tu non l'avessi definito). l'istanza p1 gli viene passata
per riferimento (notare il prototipo che hai usato: Prova& operator=(const Prova
& prova)), quindi
non è chiamato nessun costruttore poiché gli passi proprio l'indirizzo in memoria in cui è memorizzato p1.
3) esatto, perché gli passi un oggetto per copia.
4) qui c'è un accenno importante da fare. l'istruzione Prova() restituisce un
oggetto temporaneo senza nome. in c++11, per questo tipo di oggetti (che vengono chiamati rvalue references) c'è una notazione speciale ovvero il doppio reference (Prova&&), questo perché nel c++11 è stato introdotto il concetto dello
spostamento: nel c++ "vecchio" avresti avuto temporaneamente l'oggetto senza nome creato da Prova(), che veniva
copiato nell'oggetto con nome p5. nel c++11 invece l'oggetto senza nome viene
spostato direttamente dentro p5, quindi non viene richiamato il costruttore copia poichè non si tratta di una copia, bensì di uno
spostamento.
5) stesso discorso per il punto precedente.