ProgrammierungC++ Entwickler

Wie unterscheiden sich Shallow Copy und Deep Copy in C++? In welchen Situationen sollte man das tiefe Kopieren selbst implementieren, und wie macht man das richtig?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

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:

  • Wenn das Objekt über dynamisch zugewiesenen Speicher verfügt.
  • Wenn Änderungen am Inhalt eines Objekts keine Auswirkungen auf ein anderes haben sollten.

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 mit einem Trick.

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.

Beispiele für reale Fehler aufgrund unzureichenden Wissens über die Feinheiten des Themas.


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.