PDA

Visualizza la versione completa : [C++] Costruttori di copia e operatore di assegnamento


fabi080
24-11-2005, 20:57
Ciao a tutti, ho un dubbio, se io in C scrivo


int f(...) {
int a;
...
return a;
}

e poi nel codice uso la funzione ad esempio con


int b = f(...);

tutto ciò non crea nessun problema, semplicemente il valore di ritorno presente sullo stack viene copiato nella variabile b.

Ora in C++, non mi è ben chiaro il meccanismo di copia/assegnamento degli oggetti soprattutto quelli ritornati dalle funzioni, ho scritto una classe di esempio per cercare di capire meglio come avviene il tutto, ma ci sono alcuni punti che non mi sono chiarissimi (forse per via di alcune ottimizzazioni fatte dal compilatore)



class foo {
unsigned ser;
public:
static unsigned serial;
foo() {
ser = ++serial;
cout << "creating " << ser << endl;
};
foo(const foo &t) {
this->ser = t.ser;
cout << "copy " << t.ser << " to " << this->ser << endl;
};
const foo &operator=(const foo &that) {
cout << "assign " << that.ser << " to " << this->ser << endl;
this->ser = that.ser;
return *this;
};
};

unsigned foo::serial = 0;

Ora se nel main scrivo


foo g() {
foo a;
return a; // questo sta sullo stack
}

int main() {
foo foo1 = g();
foo foo2;
foo2 = foo1;
foo foo3 = foo1;
}

ho come output


creating 1
creating 2
assign 1 to 2
copy 1 to 1

mentre io mi aspetterei, tra parentesi il perchè


creating 1 (per creare a)
copy 1 to 1 (dallo stack a foo1, o in alternativa assign)
creating 2 (ok)
assign 1 to 2 (ok)
creating 3 (crea l'oggetto foo3)
assign 1 to 3 (assegna foo1)

Qualcuno sa spiegarmi meglio questo meccanismo, in particolare mi sfugge il perchè non viene chiamato il costruttore di copia quando ritorno a dalla funzione, il fatto che foo3 non sia creato immagino sia giusto perchè è inutile creare l'oggetto foo3 al solo scopo di assegnargli qualcosa, si fa direttamente una copia di foo1 e via.

Inoltre se io ho una funzione come g, posso usare tranquillamente il valore di ritorno senza il timore di usare qualcosa che sta sullo stack e che alla prossima chiamata a funzione non esiste più? Immagino di si a patto di non assegnare ad a (o a qualche suo campo) puntatori ad oggetti/variabili locali alla funzione.

Grazie per le risposte.

AlessioR
25-11-2005, 00:56
Il problema è che il compilatore è ottimizzato, nella prima chiamata, quella a g() quello che ritorna come oggetto temporaneo anonimo (return a) è utilizzato per inizializzare foo1.

Per foo2 tutto ok, l'hai capito anche tu.

Per foo3 se tu al momento della dichiarazione assegni qualcosa usa il costruttore e non l'assegnazione.
Cioè:
foo foo3 = foo1;
è uguale a scrivere:
foo foo3(foo1);

Loading