Tiefes Kopieren VS Untiefe Kopieren in C++
- Flache Kopie wird vom Standardkopierkonstruktor in C++ verwendet
- Verwenden des benutzerdefinierten Kopierkonstruktors zur Implementierung des Deep-Copy-Verhaltens in C++
In diesem Artikel werden verschiedene Methoden zur Verwendung von Deep Copy VS Flat Copy in C++ beschrieben.
Flache Kopie wird vom Standardkopierkonstruktor in C++ verwendet
C++ Klassen werden im Allgemeinen mit mehreren Operationen definiert, die zusammen als Kopiersteuerung
bezeichnet werden und vom Benutzer explizit oder implizit vom Compiler angegeben werden. Diese Elementfunktionen werden bezeichnet als: Kopierkonstruktor
, Kopierzuweisungsoperator
, Verschiebungskonstruktor
, Verschiebungszuweisungsoperator
und Destruktor
. Kopierkonstruktor und Verschiebungskonstruktor implementieren Operationen, die auftreten, wenn das Objekt von einem anderen Objekt desselben Typs initialisiert wird. Wenn diese Funktionen vom Compiler implizit synthetisiert werden, verhalten sich einige Klassentypen möglicherweise falsch. Beispielsweise teilen die Klassen, die den dynamischen Speicher verwalten, Datenelemente, die manuell zugewiesen werden müssen. Somit ist der Programmierer dafür verantwortlich, die obigen Mitgliedsfunktionen explizit zu implementieren.
In diesem Fall demonstrieren wir den Fall eines Kopierkonstruktors in einer Klasse mit dem Namen Person
mit zwei Datenelementen std::string
, von denen eines mit dem Operator new
zugewiesen wird. Der folgende Beispielcode zeigt, was passiert, wenn der Kopierkonstruktor nicht explizit definiert ist und wir ein Person
-Objekt mit einem anderen Person
-Objekt initialisieren. Beachten Sie, dass P1
Zeichenketten gespeichert hat - Buddy
/ Rich
nach der Initialisierung und P2
dieselben Werte hat, nachdem der Kopierkonstruktor in der Anweisung - Person P2 = P1;
aufgerufen wurde. Nachdem die Funktion renamePerson
für das Objekt P1
ausgeführt wurde, wird auch das Datenelement Nachname
des Objekts P2
geändert.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Person {
public:
Person() = default;
Person(string n, string s) {
name = std::move(n);
surname = new string(std::move(s));
}
~Person() { delete surname; }
void renamePerson(const string &n, const string &s) {
name.assign(n);
surname->assign(s);
};
string &getName() { return name; };
string &getSurname() { return *surname; };
void printPerson() { cout << name << " " << *surname; }
private:
string name;
string *surname{};
};
int main() {
Person P1("Buddy", "Rich");
Person P2 = P1;
P1.printPerson();
cout << endl;
P2.printPerson();
cout << endl;
P1.renamePerson("Heinz", "Lulu");
P1.printPerson();
cout << endl;
P2.printPerson();
cout << endl;
exit(EXIT_SUCCESS);
}
Ausgabe:
Buddy Rich
Buddy Rich
Heinz Lulu
Buddy Lulu
Verwenden des benutzerdefinierten Kopierkonstruktors zur Implementierung des Deep-Copy-Verhaltens in C++
Wenn wir dagegen einen benutzerdefinierten Kopierkonstruktor für die Klasse Person
implementieren, verhält er sich korrekt und ändert das Objekt P2
nach der Anweisung P1.renamePerson("Heinz", "Lulu")
nicht. Im vorherigen Codeausschnitt zeigte das Mitglied Nachname
des Objekts P2
auf dieselbe Zeichenkette wie das Objekt P1
, und renamePerson
hat beide Objekte geändert. Dieses Mal hat P2
ein eigenes Mitglied mit dem Namen Nachname
im dynamischen Speicher und teilt es nicht mit dem Objekt P1
.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Person {
public:
Person() = default;
Person(string n, string s) {
name = std::move(n);
surname = new string(std::move(s));
}
Person(Person &p) {
name = p.name;
surname = new string(*p.surname);
}
~Person() { delete surname; }
void renamePerson(const string &n, const string &s) {
name.assign(n);
surname->assign(s);
};
string &getName() { return name; };
string &getSurname() { return *surname; };
void printPerson() { cout << name << " " << *surname; }
private:
string name;
string *surname{};
};
int main() {
Person P1("Buddy", "Rich");
Person P2 = P1;
P1.printPerson();
cout << endl;
P2.printPerson();
cout << endl;
P1.renamePerson("Heinz", "Lulu");
P1.printPerson();
cout << endl;
P2.printPerson();
cout << endl;
exit(EXIT_SUCCESS);
}
Ausgabe:
Buddy Rich
Buddy Rich
Heinz Lulu
Buddy Rich
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook