Copie superficielle et copie profonde
Dans la classe Circle, l'exemple du constructeur de copie expliqué dans la section précédente, la stratégie de copie est cohérente avec la stratégie par défaut du système, c'est-à-dire que les membres de l'objet d'origine sont copiés dans l'ordre vers les membres correspondants du nouvel objet. Dans ce cas, pourquoi voulons-nous encore le définir vous-même ? La raison en est que le simple fait d'initialiser toutes les situations de cette manière simple entraînera inévitablement des problèmes dans différentes situations.
Par exemple, dans la classe Circle tout à l'heure, si un membre pointeur est ajouté à la variable membre et que la mémoire doit être allouée dynamiquement lors de l'initialisation, il y aura un énorme risque de sécurité. Le code est le suivant :
/************************************//Des : programme de support du didacticiel C++//Auteur :Huang //CopyRight:www.dotcpp.com//Date:2017/8/26***************************** ** ******/#include<i ostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);~Circle();doublearea();doublegir th();};Circle::~Circle(){delete[]str;}Circle::Circle(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 (){CercleA(5,NO.1Oldclass);CircleB(A);return0;}
Pour vérifier, dans la classe Circle, nous avons ajouté un membre pointeur et l'avons initialisé dans le constructeur sans constructeur de copie personnalisé. Ensuite, dans la fonction principale, la phrase Circle B(A); attribue l'objet A à l'objet B et appelle le constructeur de copie généré par défaut. Après l'exécution, le programme signale une erreur comme indiqué ci-dessous :
La véritable raison est que le constructeur de copie par défaut effectue uniquement l'affectation des données et ne peut pas ouvrir d'espace mémoire pour les pointeurs, ce qui équivaut au code :
Ceci->str=str;
Donc, essentiellement, deux pointeurs pointent vers un morceau d’espace de tas. Cela va à l’encontre de notre intention initiale. Puis à la fin du programme, lorsque les deux objets seront recyclés, leurs propres destructeurs seront appelés pour libérer cet espace mémoire. Puisque les deux objets devront être appelés deux fois, c'est-à-dire supprimés deux fois, une erreur se produira !
Par conséquent, lorsqu'il y a un type de pointeur dans la classe, s'appuyer sur la méthode de constructeur de copie par défaut ne peut plus répondre à nos besoins. Un constructeur de copie spécifique doit être défini, qui peut non seulement copier les données, mais également allouer de l'espace mémoire aux membres. pour réaliser une copie réelle, également appelée copie profonde, il s'agit du constructeur de copie profonde .
Implémentation du constructeur de copie profonde :
#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);Circle(Circle&A);~ Circle();doublearea();doublegirth();};Circle::~Circle(){delete[]str;cout<<CallDestructor<<endl;}Circle::Circle(Circle&A){cout<<CopyConstructor<< fin; ceci -> R =AR;this->str=newchar[strlen(A.str)+1];strcpy(this->str,A.str);}Circle::Circle(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::girth(){return2*PI*R;}intmain(){CircleA (5,NO.1Oldclass);CercleB(A);return0;}
Le principe d'implémentation est similaire au constructeur avec paramètres. Un espace mémoire suffisant est ouvert avant l'affectation pour véritablement terminer la copie complète. C'est ce qu'on appelle la « copie approfondie ». Veuillez comprendre et essayer sur l'ordinateur !