Newsgroup: it.comp.lang.c++
Titolo: Costruttore di copia

Salve ragazzi sono alle prese con lo studio del costruttore di copia, se il
mio libro non si sbaglia, i casi in cui è opportuno usarlo sono 3: quando
un oggetto inizializza esplicitamente un altro oggetto, quando la copia di
un oggetto viene passata come paramentro ad una funzione e quando viene
generato un oggetto temporaneo, più comunemente come valore di
restituzione. Premesso questo devo implementare una lista che si ritrovi in
una delle 3 situazioni prima citate, per così utilizzare un costruttore di
copia, ma non riesco a creare una situazione per metterlo in atto. Cosa
vuol dire che un oggetto inizializza esplicitamente un altro, a cosa serve
passare la copia di un oggetto ad una funzione e soprattutto perchè dovrei
restituire un oggetto in una funzione? Spero che qualcuno vorrà aiutarmi a
capire meglio come e perchè usare un costruttore di copia, grazie :-D

e soprattutto perchè dovrei restituire un oggetto in una funzione?
y = func(y) //y riceve da func() un oggetto temporaneo

Acaccia wrote:

Allora perchè questo codice che inizializza un oggetto ad un'altro funziona
perfettamente anche senza un costruttore di copia? 
#include <iostream>
using namespace std;
struct nodo
{
    int dato;
    struct nodo* next;
};
typedef struct nodo NODO;
class lista
{
    private:
            NODO* testa;
            NODO* fine;
    public:
            lista();
            ~lista();
            void creazione();
            void mostra();
};
lista::lista()
{
     testa=NULL; fine=NULL;
}
lista::~lista()
{
    NODO* aux;
    while(testa)
    {
        aux=testa;
        testa=testa->next;
        delete (aux);
    }
}
void lista::creazione()
{
        NODO* aux;
        int x;
        cout<<"Inserire numero"<<endl;
        cin>>x;
        while(x)
        {
                aux= new (NODO);
                aux->dato=x;
                aux->next=NULL;
                if(!testa)
                        testa=aux;
                else
                        fine->next=aux;
                fine=aux;
                cout<<"Inserire numero"<<endl;
                cin>>x;
        }
}
void lista::mostra()
{
   NODO* aux=testa;
   while(aux)
   {
        cout<<aux->dato<<endl;
        aux=aux->next;
   }
   cout<<endl;
}
int main()
{
    lista lista1;
    lista lista2;
    lista1.creazione();
    lista1.mostra();
 
    lista2=lista1;
    lista2.mostra();
return 0;
}

 perfettamente anche senza un costruttore di copia? 
Prova a scrivere
    lista lista3 = lista1;
in fondo al tuo main e da quel punto in poi lista1 e lista3
saranno indebitamente "intrecciati tra loro"....
- Dario

Dario ca?èinomane wrote:

Che vuol dire che saranno intrecciati?

 restituzione. 
Questi non sono casi in cui e' opportuno usare il costruttore di
copia; sono casi in cui il compilatore *usa* il costruttore di copia,
quello definito da te esiste altrimenti quello che genera
automaticamente.
I casi in cui conviene *definire* un costruttore di copia sono quelli
in cui il costruttore di copia di default non si comporta in modo
sensato. Dal momento che quello di default esegue la copia membro a
membro, il caso piu' tipico da gestire esplicitamente e' quando la tua
classe ha un membro dato di tipo puntatore e tu non vuoi che dopo la
copia l'oggetto originale e la copia puntino allo stesso oggetto.
Ciao,
Nicola

 perfettamente anche senza un costruttore di copia?
A parte il fatto che nel codice che mi hai postato non viene chiamato il
costruttore di copia, perchè come ti ho scritto viene chiamato solo nel caso
di inizializzazione ma quando tu scrivi:
lista x;
lista y; << viene chiamato il costruttore di lista cioè lista()
y = x; << viene chiamato l'operatore = che da te non viene definito, quindi
il comportamento dovrebbe essere indefinito (in C++ quando non ridefinisci
l'operatore =, viene automaticamente creato per te un operatore = che esegue
la copia bit a bit e membro a membro dell'oggetto in questione).
Ad ogni modo come per l'operatore =,  anche  quando tu non dichiari alcun
costruttore di copia il compilatore dovrebbe crearne uno per ed eseguire la
copia bit a bit, ma questo potrebbe non essere il comportamento da te
desiderato, per cui si ha bisogno di crearne uno proprio.
Ciao

Giovanni wrote:

La tua classe lista manca di un copy-constructor (costruttore di copia)
e di un assignment operator (operatore di assegnamento =).
La mancanza di copy-constructor si può dedurre
da questo programmino di prova:
int main() {
   lista lista1;
   lista1.creazione();
   lista lista2 = lista1;
   /* QUI IL PROBLEMA */
   return 0;
}
Mancando un adeguato copy-constructor il compilatore traduce
   lista lista2 = lista1;
copiando bit a bit i campi di lista1 in lista2.
Facendo così lista2 e lista1
    NON sono due liste diverse con due _divere_ catene di STRUCT nodo;
ma
    sono due liste diverse che condividono la _stessa_ catena di nodi.
La mancanza di un operator assegnamento si può dedurre
da questo programmino di prova:
int main() {
   lista lista1;
   lista lista2;
   lista1.creazione();
   lista2.creazione();
   lista2 = lista1;
   /* QUI IL PROBLEMA */
   return 0;
}
Mancando un adeguato operatore di assegnamento il compilatore traduce
   lista2 = lista1;
copiando bit a bit i campi di lista1 in lista2.
Facendo così si ha
   - lo stesso problema evidenziato sopra per il copy-constructor,
   - aggravato poi dal fatto che tutti i nodi originariamente presenti
     in lista2 _non_ saranno più accessibili ma continueranno ad
     esistere sullo heap perchè nessuno ha provveduto a chiamare
     le delete per loro.
- Dario

 func (y) //y passata per valore -> creazione di una copia
questo andrebbe bene se la dichiarazione di func fosse
	func(Y );	// Y è un tipo per y
ma se invece fosse
	func(Y&);
verrebbe passato un riferimento a y nel caso di func(y).
Saluti
-- 
http://www.parashift.com/c++-faq-lite/
http://mindview.net/Books/DownloadSites
http://www.cppreference.com/

 verrebbe passato un riferimento a y nel caso di func(y).
Certo. Infatti ho scritto "y passata per valore" non "y passata per
riferimento".
Ciao.