ProgramaciónDesarrollador C++

¿Cuáles son las diferencias entre shallow copy y deep copy en C++? ¿En qué situaciones deberías implementar la copia profunda por ti mismo y cómo hacerlo correctamente?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Shallow copy (copia superficial) - copia solo los valores de los campos del objeto, incluidos los punteros, pero no duplica la memoria asignada dinámicamente. Como resultado, ambos objetos apuntan a la misma área de memoria. Esto puede provocar errores al modificar datos o liberar memoria.

Deep copy (copia profunda) - crea una copia completa de todos los recursos a los que el objeto hace referencia, de modo que cada objeto posea su propia copia de los datos.

Cuándo necesitas deep copy:

  • Cuando el objeto posee memoria asignada dinámicamente.
  • Cuando cambiar el contenido de un objeto no debe afectar a otro.

Ejemplo de implementación de deep copy:

class ArrayHolder { public: ArrayHolder(size_t size) : sz(size), data(new int[size]) {} ~ArrayHolder() { delete[] data; } // Constructor de copia profunda ArrayHolder(const ArrayHolder& other) : sz(other.sz), data(new int[other.sz]) { std::copy(other.data, other.data + other.sz, data); } // Asignación de copia profunda ArrayHolder& operator=(const ArrayHolder& other) { if (this != &other) { delete[] data; sz = other.sz; data = new int[sz]; std::copy(other.data, other.data + sz, data); } return *this; } private: size_t sz; int* data; };

Pregunta capciosa.

Pregunta: ¿Funcionará correctamente el constructor de copia si simplemente copias el valor del puntero?

Respuesta: No, esto provocará una eliminación doble de la memoria al destruir ambos objetos. Es necesario implementar la copia profunda para gestionar correctamente los recursos.

Ejemplos de errores reales debido a la falta de conocimiento sobre las sutilezas del tema.


Historia

En uno de los proyectos, para transferir matrices entre módulos, se utilizaron objetos de una clase donde el constructor de copia predeterminado solo copiaba el puntero (shallow copy). Como resultado, después de que el objeto temporal saliera del alcance, la matriz se destruía, mientras que el objeto principal quedaba con un puntero "suspendido", lo que llevaba a un comportamiento indefinido y al bloqueo de la aplicación.


Historia

En una biblioteca para trabajar con imágenes, se copiaron varias veces objetos que contenían búferes asignados dinámicamente. Debido a la falta de deep copy, después de liberar la memoria en un objeto, otro accedía a la zona liberada. Esto resultó en daños de datos y bloqueos al eliminar el objeto.


Historia

Al integrar código obsoleto con estándares modernos, en las clases antiguas no se implementaron ni el constructor de copia ni el operador de asignación. Usar estas clases con contenedores de la biblioteca estándar provocó fallos inesperados, ya que los contenedores copiaban objetos de manera superficial.