Bei der Übergabe eines Objekts per Wert an eine Funktion in C++ passiert die Erstellung einer Kopie des Objekts mithilfe des Kopierkonstruktors. Wenn in der Klasse ein benutzerdefinierter Kopierkonstructor definiert ist, wird dieser aufgerufen, um das temporäre Objekt-Argument der Funktion zu initialisieren. Wenn kein solcher definiert ist, wird der standardmäßige Compiler verwendet, der eine bitweise Kopie (shallow copy) durchführt.
Fallstricke:
Beispiel:
class StringWrapper { char* data; public: StringWrapper(const char* str) { data = new char[strlen(str) + 1]; strcpy(data, str); } // Fehler: shallow copy StringWrapper(const StringWrapper& other) : data(other.data) {} ~StringWrapper() { delete [] data; } }; void foo(StringWrapper s) { // ... } int main() { StringWrapper s1("hello"); foo(s1); // UB!!! return 0; }
"Was passiert, wenn der Kopierkonstruktor in einer Klasse mit einem Zeiger so definiert wird:
MyClass(const MyClass &other) : data(other.data) {}? Welche Folgen hat das?"
Richtige Antwort: Ein solcher Kopierkonstruktor erstellt ein Objekt mit einem Zeiger auf denselben Speicherbereich wie das kopierte Objekt. Bei der Zerstörung der beiden Objekte wird der Speicher zweimal freigegeben (double free), was zu undefiniertem Verhalten führt. Es sollte eine deep copy implementiert werden:
MyClass(const MyClass &other) { data = new int(*other.data); }
Geschichte
In einem großen Serverprojekt wurden Container aus Objekten mit einem "rohen" Array darin und dem standardmäßigen Kopierkonstruktor (shallow copy) verwendet. Bei der Übergabe von Objekten per Wert traten double free und Anwendungsabstürze auf, die nur in der Produktion erfasst wurden.
Geschichte
In einer alten C++-Bibliothek zur Verarbeitung von Bildern kopierte der Kopierkonstruktor den Grafikpuffer nicht, was dazu führte, dass sich eine Kopie des Bildes änderte, wenn die andere geändert wurde, und unerwartete Bugs in der Benutzeroberfläche auftraten.
Geschichte
Beim Zurückgeben eines Objekts per Wert aus einer Funktion in einem der internen Passwortspeichersysteme wurden die Daten beim Zerstören des temporären Objekts (shallow copy) gelöscht, wodurch das echte Objekt einen nullzeiger enthielt, und das Leck wurde zufällig während einer Sicherheitsüberprüfung entdeckt.