BUSCAR
INDICE
INDICE DEL TEMA
OBJETIVOS
TEORIA
PALABRAS RESERVADAS
GLOSARIO
EJERCICIOS
RESUELTOS
AUTOEVALUACION
PROPUESTOS
ERRORES
ESTADISTICAS
INICIO
FAQS
LINKS
RECOMIENDANOS
QUIENES SOMOS
MAPA DEL WEB
COLABORAR
Tema 22 Constructores y Destructores
Teoría: Necesidad de escribir un constructor de copia

Ha llegado ya el momento de explicar cómo surge la necesidad de escribir un constructor de copia distinto del que proporciona el compilador. Considérese una clase Alumno con dos variablesmiembro: un puntero a char llamado nombre y un long llamado nmat que representa el número de matrícula..

class Alumno {
char* nombre;
long nmat;
...
};

En realidad, esta clase no incluye el nombre del alumno, sino sólo un puntero a carácter que permitirá almacenar la dirección de memoria donde está realmente almacenado el nombre. Esta memoria se reservará dinámicamente cuando el objeto vaya a ser inicializado. Lo importante es darse cuenta de que el nombre no es realmente una variable miembro de la clase: la variable miembro es un puntero a la zona de memoria donde está almacenado. Esta situación se puede ver gráficamente en la figura 1, en la que se muestra un objeto a de la clase Alumno.

Supóngase ahora que con el constructor de copia suministrado por el compilador se crea un nuevo objeto b a partir de a. Las variables miembro de b van a ser una copia bit a bit de las del objeto a. Esto quiere decir que la variable miembro b.nombre contiene la misma dirección de memoria que a.nombre. Esta situación se representa gráficamente en la figura 2: ambos objetos apuntan a la misma dirección de memoria.

La situación mostrada en la figura 2 puede tener consecuencias no deseadas. Por ejemplo, si se quiere cambiar el nombre del Alumno a, lo primero que se hace es liberar la memoria a la que apunta a.nombre, reservar memoria para el nuevo nombre haciendo que a.nombre apunte al comienzo de dicha memoria, y almacenar allí el nuevo nombre de a. Como el objeto b no se ha tocado, su variable miembro b.nombre se ha quedado apuntado a una posición de memoria que ha sido liberada en el proceso de cambio de nombre de a. La consecuencia es que b ha perdido información y los más probable es que el programa falle.

Se llega a una situación parecida cuando se destruye uno de los dos objetos a o b. Al destruir uno de los objetos se libera la memoria que comparten, con el consiguiente perjuicio para el objeto que queda, puesto que su puntero contiene la dirección de una zona de memoria liberada, disponible para almacenar otra información.

Finalmente, la figura 3 muestra la situación a la que se llega con un constructor de copia correctamente programado por el usuario. En este caso, el constructor no copia bit a bit la dirección contenida en a.nombre, sino que reserva memoria, copia a esa memoria el contenido apuntado por a.nombre, y guarda en b.nombre la dirección de esa nueva memoria reservada. Ninguno de los problemas anteriores sucede ahora.