2012-08-23 15 views
5

Un constructor de copia se utiliza para muchas cosas, como cuando necesito utilizar punteros o asignar dinámicamente memoria para un objeto. Pero al mirar a este ejemplo a tutorialpoint.com:Explaining copy constructor example

#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; 
} 

el resultado es:

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

y cuando me comentó a cabo (el constructor de copia) y el código dentro destructor Me dieron los mismos resultados:

Normal constructor allocating ptr 
Length of line : 10 

¿Cuál es la diferencia entre usar el constructor de copia aquí o no? Además, ¿por qué "Freeing Memory"? ocurrir dos veces?

+2

Mira los resultados. En el primer ejemplo, estás asignando dos entradas diferentes y liberándolas a ambas. En el segundo, asigna uno y lo libera dos veces. No está bien. – chris

+0

no se libera en el segundo ejemplo, me olvidé de comentar la "liberación de memoria" cout < Omar

+0

Luego ha asignado algo que no ha liberado, que es una pérdida de memoria si comienza a volverse más complejo que simplemente crear uno y finalizar el programa. – chris

Respuesta

3

El argumento para la función display() se pasa por valor, por lo que el compilador llama al constructor de copia para crearlo. Cuando la clase define su constructor de copia se obtiene la semántica correcta: el constructor de copia hace una copia, y esa copia tiene su propia memoria para mantener la longitud. Cuando elimina el constructor de copia, el compilador genera uno para usted y la copia que pasa a display() tiene el mismo puntero que el original. Cuando esa copia se destruye, elimina la memoria a la que apunta ptr. Cuando se destruye el original, se borra la misma memoria (que aquí no tiene efectos visibles). Definitivamente eso no es lo que quiere que suceda, por lo que necesita definir un constructor de copia. Como dice @Joe: dentro del destructor, imprima el valor de `ptr 'para ver esto más claramente.

4

Imprime la dirección de la memoria liberada.

Creo que encontrará que el compilador generó el constructor por usted, hizo una copia valiosa de los contenidos, incluido el puntero, y está liberando el puntero y simplemente teniendo suerte de que el tiempo de ejecución no se queje al respecto .

El constructor de copia generado por el compilador todavía se está llamando; nada ha cambiado en ese sentido, simplemente no está imprimiendo nada desde que no lo escribió.

0

Un constructor de algún tipo T de la forma

T (const & T); 

El único argumento debe ser una referencia const a un objeto existente de mismo tipo crea un duplicado del objeto existente utilizada cuando una copia de una se necesita objeto Incluyendo argumentos a funciones, resultados devueltos por las funciones Problemas con matrices basadas en puntero en C++: - Sin comprobación de rango. No se puede comparar de manera significativa con == Sin asignación de matriz (los nombres de matriz son punteros const). Si la matriz pasó a una función, el tamaño se debe pasar como un argumento separado.

1

Si no definimos nuestro propio constructor de copia, el compilador de C++ crea un constructor de copia predeterminado para cada clase que hace una copia entre los objetos. El compilador creado constructor de copias funciona bien en general. Necesitamos definir nuestro propio constructor de copia solo si un objeto tiene punteros o cualquier asignación de tiempo de ejecución de recursos como manejador de archivos, una conexión de red ...