2012-08-23 2 views
5

Un costruttore di copia viene utilizzato per molte cose, ad esempio quando è necessario utilizzare i puntatori o allocare dinamicamente la memoria per un oggetto. Ma guardando questo esempio a tutorialpoint.com:Spiegazione dell'esempio del costruttore di copia

#include <iostream> 

using namespace std; 

class Line 
{ 
public: 
    int getLength(void); 
    Line(int len);    // simple constructor 
    Line(const Line &obj); // copy constructor 
    ~Line();      // destructor 

private: 
    int *ptr; 
}; 

// Member functions definitions including constructor 
Line::Line(int len) 
{ 
cout << "Normal constructor allocating ptr" << endl; 
// allocate memory for the pointer; 
ptr = new int; 
*ptr = len; 
} 

Line::Line(const Line &obj) 
{ 
cout << "Copy constructor allocating ptr." << endl; 
ptr = new int; 
*ptr = *obj.ptr; // copy the value 
} 

Line::~Line(void) 
{ 
cout << "Freeing memory!" << endl; 
delete ptr; 
} 
int Line::getLength(void) 
{ 
return *ptr; 
} 

void display(Line obj) 
{ 
    cout << "Length of line : " << obj.getLength() <<endl; 
} 

// Main function for the program 
int main() 
{ 
    Line line(10); 

    display(line); 

    return 0; 
} 

il risultato è:

Normal constructor allocating ptr 
Copy constructor allocating ptr. 
Length of line : 10 
Freeing memory! 
Freeing memory! 

e quando ho commentato fuori (il costruttore di copia) e il codice all'interno distruttore ho ottenuto gli stessi risultati:

Normal constructor allocating ptr 
Length of line : 10 

Quindi qual è la differenza tra l'utilizzo del costruttore di copie qui o no? Anche perché fa "Liberare memoria!" si verificano due volte?

+2

Guarda i risultati. Nel primo esempio, stai allocando due diversi ints e liberandoli entrambi. Nel secondo, ne assegni uno e lo liberi due volte. Non bene. – chris

+0

non è stato liberato nel secondo esempio, ho semplicemente dimenticato di commentare il "cout <<" liberare memoria!"affermazione all'interno del costruttore, quindi non è stata liberata. – Omar

+0

Quindi hai assegnato qualcosa che non hai liberato, che è una perdita di memoria se inizia a diventare più complesso della semplice creazione di uno e termina il programma. – chris

risposta

3

L'argomento della funzione display() viene passato per valore, quindi il compilatore chiama il costruttore di copie per crearlo. Quando la classe definisce il suo costruttore di copie si ottiene la semantica corretta: il costruttore di copie crea una copia e quella copia ha la sua memoria per contenere la lunghezza. Quando si rimuove il costruttore di copie, il compilatore ne genera uno per te e la copia passata a display() ha lo stesso puntatore dell'originale. Quando quella copia viene distrutta, cancella la memoria a cui punta ptr. Quando l'originale viene distrutto, cancella di nuovo la stessa memoria (che in questo caso non ha effetti visibili). Questo non è sicuramente quello che vuoi che accada, ed è per questo che devi definire un costruttore di copie. Come dice @Joe: all'interno del distruttore, stampa il valore di `ptr 'per vederlo più chiaramente.

4

Stampa l'indirizzo della memoria liberata.

Credo che troverete che il compilatore ha generato il costruttore per voi, ha fatto una copia del valore del contenuto, incluso il puntatore, e voi state liberando il puntatore e ottenendo solo fortuna che il runtime non si lamenta di esso .

Il costruttore di copia generato dal compilatore viene ancora chiamato - non è cambiato nulla a tale riguardo, non si stampa nulla da esso poiché non è stato scritto.

0

Un costruttore di un certo tipo T della forma

T (const & T); 

Il singolo argomento deve essere un riferimento const a un oggetto esistente dello stesso tipo Crea un duplicato dell'oggetto esistente usati quando una copia di un oggetto è necessario Inclusi gli argomenti alle funzioni, i risultati restituiti dalle funzioni Problemi con gli array basati su puntatori in C++: - Nessun controllo di intervallo. Non può essere confrontato in modo significativo con == Assenza di array (i nomi degli array sono puntatori const). Se la matrice passa a una funzione, la dimensione deve essere passata come argomento separato.

1

Se non definiamo il nostro costruttore di copie, il compilatore C++ crea un costruttore di copie predefinito per ogni classe che fa una copia membro tra gli oggetti. Il compilatore creato copia il costruttore funziona bene in generale. Dobbiamo definire il nostro costruttore di copie solo se un oggetto ha puntatori o qualsiasi allocazione di risorse di run time come handle di file, una connessione di rete ..

Problemi correlati