Flache Kopie und tiefe Kopie
In der Circle-Klasse, dem im vorherigen Abschnitt erläuterten Beispiel des Kopierkonstruktors, stimmt die Kopierstrategie mit der Standardstrategie des Systems überein, dh die Mitglieder des ursprünglichen Objekts werden nacheinander in die entsprechenden Mitglieder des neuen Objekts kopiert. Warum tun wir in diesem Fall immer noch? Möchten Sie es selbst definieren? Der Grund dafür ist, dass die einfache Initialisierung aller Situationen auf diese einfache Weise unweigerlich zu Problemen in verschiedenen Situationen führt.
Wenn beispielsweise in der Circle-Klasse gerade ein Zeigermitglied zur Mitgliedsvariablen hinzugefügt wird und der Speicher während der Initialisierung dynamisch zugewiesen werden muss, besteht ein großes Sicherheitsrisiko. Der Code lautet wie folgt:
/****************************************//Des: C++-Tutorial-Unterstützungsprogramm//Autor: Huang //CopyRight:www.dotcpp.com//Datum:26.08.2017****************************** ** ******/#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);~Circle(); doublearea( );doublegirth();};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(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
Zur Überprüfung haben wir in der Circle-Klasse ein Zeigerelement hinzugefügt und es im Konstruktor ohne einen benutzerdefinierten Kopierkonstruktor initialisiert. Dann weist der Satz Circle B(A); das A-Objekt dem B-Objekt zu und ruft den standardmäßig generierten Kopierkonstruktor auf. Nach der Ausführung meldet das Programm einen Fehler wie unten gezeigt:
Der eigentliche Grund ist, dass der Standardkopierkonstruktor nur die Datenzuweisung durchführt und keinen Speicherplatz für Zeiger öffnen kann, was dem Code entspricht:
This->str=str;
Im Wesentlichen zeigen also zwei Zeiger auf ein Stück Heap-Speicherplatz. Es widersprach unserer ursprünglichen Absicht. Wenn die beiden Objekte am Ende des Programms recycelt werden, werden ihre eigenen Destruktoren aufgerufen, um diesen Speicherplatz freizugeben. Da die beiden Objekte zweimal aufgerufen, dh zweimal gelöscht werden müssen, tritt ein Fehler auf!
Wenn die Klasse einen Zeigertyp enthält, kann die Verwendung der Standardkopierkonstruktormethode unsere Anforderungen nicht mehr erfüllen. Es muss ein bestimmter Kopierkonstruktor definiert werden, der nicht nur Daten kopieren, sondern auch Speicherplatz für Mitglieder zuweisen kann. Um eine echte Kopie, auch Deep Copy genannt, zu erreichen, ist dies der Deep Copy-Konstruktor .
Implementierung des Deep-Copy-Konstruktors:
#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);Circle(Circle&A);~Circle();doublerea(); doublegirth();};Circle::~Circle(){delete[]str;cout<<CallDestructor<<endl;}Circle::Circle(Circle&A){cout<<CopyConstructor<<endl;this->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);CircleB(A);return0;}
Das Implementierungsprinzip ähnelt dem Konstruktor mit Parametern. Vor der Zuweisung wird ausreichend Speicherplatz geöffnet, um die vollständige Kopie wirklich abzuschließen. Bitte haben Sie Verständnis und probieren Sie es am Computer aus!