Shallow Copy (flächiges Kopieren) – kopiert nur die Werte der Felder des Objekts, einschließlich der Zeiger, dupliziert jedoch nicht den dynamisch zugewiesenen Speicher. Infolgedessen zeigen beide Objekte auf denselben Speicherbereich. Dies kann zu Fehlern führen, wenn Daten geändert oder der Speicher freigegeben wird.
Deep Copy (tiefes Kopieren) – erstellt eine vollständige Kopie aller Ressourcen, auf die das Objekt verweist, sodass jedes Objekt seine eigene Kopie der Daten besitzt.
Wann ist Deep Copy notwendig:
Beispiel für die Implementierung von Deep Copy:
class ArrayHolder { public: ArrayHolder(size_t size) : sz(size), data(new int[size]) {} ~ArrayHolder() { delete[] data; } // Deep Copy Konstruktor ArrayHolder(const ArrayHolder& other) : sz(other.sz), data(new int[other.sz]) { std::copy(other.data, other.data + other.sz, data); } // Deep Copy Zuweisungsoperator ArrayHolder& operator=(const ArrayHolder& other) { if (this != &other) { delete[] data; sz = other.sz; data = new int[sz]; std::copy(other.data, other.data + sz, data); } return *this; } private: size_t sz; int* data; };
Frage: Wird der Kopierkonstruktor korrekt funktionieren, wenn einfach der Wert des Zeigers kopiert wird?
Antwort: Nein, das würde zu doppeltem Löschen des Speichers bei der Zerstörung beider Objekte führen. Es ist notwendig, tiefes Kopieren zu implementieren, um die Ressourcen korrekt zu verwalten.
Geschichte
In einem der Projekte wurden Objekte einer Klasse verwendet, um Arrays zwischen Modulen zu übertragen, wobei der Kopierkonstruktor standardmäßig nur den Zeiger kopierte (Shallow Copy). Infolgedessen wurde das Array nach dem Verlassen des temporären Objekts aus dem Gültigkeitsbereich zerstört, während das Hauptobjekt mit einem „hängenden“ Zeiger zurückblieb, was zu unbestimmtem Verhalten und einem Absturz der Anwendung führte.
Geschichte
In einer Bibliothek zum Arbeiten mit Bildern wurden wiederholt Objekte kopiert, die dynamisch zugewiesene Puffer enthielten. Aufgrund des Fehlens von Deep Copy hatte nach dem Freigeben von Speicher in einem Objekt ein anderes Zugriff auf den freigegebenen Bereich. Sowohl Datenkorruption als auch Abstürze beim Löschen des Objekts traten auf.
Geschichte
Bei der Integration von veraltetem Code mit modernen Standards wurden in alten Klassen weder ein Kopierkonstruktor noch ein Zuweisungsoperator implementiert. Die Verwendung dieser Klassen mit Containern der Standardbibliothek führte zu unerwarteten Abstürzen, da die Container die Objekte flach kopierten.