Copia superficial y copia profunda
En la clase Círculo, el ejemplo del constructor de copia explicado en la sección anterior, la estrategia de copia es consistente con la estrategia predeterminada del sistema, es decir, los miembros del objeto original se copian a los miembros correspondientes del nuevo objeto en secuencia. En este caso, ¿por qué todavía? ¿Quieres definirlo tú mismo? La razón es que simplemente inicializar todas las situaciones de esta manera simple conducirá inevitablemente a problemas en diferentes situaciones.
Por ejemplo, en la clase Circle de ahora, si se agrega un miembro puntero a la variable miembro y la memoria debe asignarse dinámicamente durante la inicialización, habrá un gran riesgo de seguridad. El código es el siguiente:
/************************************//Des: Programa de soporte del tutorial C++//Autor:Huang //CopyRight:www.dotcpp.com//Fecha:2017/8/26***************************** ** ******/#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);~Circle() doublearea(; );doble circunferencia();};Círculo::~Círculo(){eliminar[]str;}Círculo::Círculo(doubleR,char*str){cout<<Constructor<<endl;this->R=R ;this ->str=newchar[strlen(str)+1];strcpy(this->str,str);cout<<this->R<<<<this->str<<endl;}doubleCircle::area () {returnPI*R*R;}doubleCircle::girth(){return2*PI*R;}intmain(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
Para verificar, en la clase Circle, agregamos un miembro puntero y lo inicializamos en el constructor sin un constructor de copia personalizado. Luego, en la función principal, la oración Circle B (A); asigna el objeto A al objeto B y llama al constructor de copia generado por defecto. Después de ejecutarse, el programa informa un error como se muestra a continuación:
La razón real es que el constructor de copia predeterminado solo realiza la asignación de datos y no puede abrir espacio de memoria para punteros, lo que equivale al código:
Esto->cadena=cadena;
Básicamente, dos punteros apuntan a una parte del espacio del montón. Ha ido en contra de nuestra intención original. Luego, al final del programa, cuando los dos objetos se reciclen, se llamará a sus propios destructores para liberar este espacio de memoria. Dado que los dos objetos deben llamarse dos veces, es decir, eliminarse dos veces, se producirá un error.
Por lo tanto, cuando hay un tipo de puntero en la clase, confiar en el método constructor de copia predeterminado ya no puede satisfacer nuestras necesidades. Se debe definir un constructor de copia específico, que no solo pueda copiar datos, sino también asignar espacio de memoria para los miembros. Para lograr una copia real, también llamada copia profunda, este es el constructor de copia profunda .
Implementación del constructor de copia profunda:
#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);Circle(Circle&A);~Circle();doublerea(); doublegirth();};Círculo::~Círculo(){eliminar[]str;cout<<CallDestructor<<endl;}Círculo::Círculo(Círculo&A){cout<<CopyConstructor<<endl;this->R=AR ;this->str=newchar[strlen(A.str)+1];strcpy(this->str,A.str);}Círculo::Círculo(doubleR,char*str){cout<<Constructor<<endl ;this->R=R;this->str=newchar[strlen(str)+1];strcpy(this->str,str);}doubleCircle::area(){returnPI*R*R;}doubleCircle: :circunferencia(){retorno2*PI*R;}intmain(){CírculoA(5,NO.1Oldclass);CírculoB(A);retorno0;}
El principio de implementación es similar al constructor con parámetros. Se abre suficiente espacio de memoria antes de la asignación para completar realmente la copia completa. Esta es la llamada "copia profunda". ¡Por favor comprenda y pruébelo en la computadora!