Introducción

Consideremos la siguiente clase:

class Persona {
    public:
        Persona(string nombre, unsigned int edad): nombre(nombre), edad(edad) {};
    private:
        string nombre;
        unsigned int edad;
};

Una copia de este objeto consistiría en copiar los valores de todos los miembros del objeto; en este caso bastaría con copiar nombre y edad.

Ahora supongamos que añadimos un nuevo miembro, que representa el sexo de la persona, en forma de puntero. ( Sigueme en el razonamiento aunque no tenga mucho sentido que sexo sea un puntero )

class Persona {
    public:
        Persona(string nombre, string *sexo, unsigned int edad):
            nombre(nombre), 
            sexo(*sexo), 
            edad(edad) {};
    private:
        string nombre;
        string *sexo;
        unsigned int edad;
};

Si copiamos los valores de todos los miembros, en el miembro sexo, se copiará la dirección de memoria y no el contenido. Por ejemplo, si tenemos varias copias del mismo objeto, todas las copias tendrán una referencia a la misma dirección de memoria; un cambio en esa dirección afecta a todas las copias.

Shallow copy (Copia superficial)

A la copia de los valores de los campos de un objeto se le conoce como copia superficial o shallow copy. Este comportamiento es el constructor de copia por defecto que genera c++.

Deep copy (Copia profunda)

Para realizar copias del contenido que apuntan los miembros dinámicos de un objeto, hay que realizar lo que se le conoce como copias profundas (deep copy). Para ello debemos crear un constructor de copia explícitamente que se encargue de realizar la copia de todos los miembros y copiar el contenido de los miembros dinámicos.

Persona::Persona(const Persona &p) {
    this->nombre = p.nombre;
    this->edad = p.edad;
    this->sexo = new string;
    memcpy((char*) this->sexo->c_str(), (char *) p.sexo->c_str(), p.sexo->size());
}

Esta manera de realizar copias permite que todas las copias sean independientes al no compartir una direccion de memoria única.

Resumen

C++ nos ofrece distintas formas de realizar copias y es necesario tener en cuenta las diferencias entre cada una de ellas.

Las copias superficiales son más rápidas de realizar en contra de las copias profundas. Las copias profundas garantizan que cada objeto tiene los datos exclusivamente para si.