Frage zum Kopierkonstruktor
-
Hallo,
ich verstehe nicht so ganz, warum der Kopierkonstruktor aufgerufen wird und was die Auswirkungen sind. Schaut euch mal bitte folgenden Code an:Array2d<int> arr(5,2); arr.init(2); Array2d<int> b(2,3); b.assign(arr);void swap (Array2d& rhs) { size_t temp = zeilen; zeilen = rhs.zeilen; rhs.zeilen = temp; temp = spalten; spalten = rhs.spalten; rhs.spalten = temp; T* tempPtr = ptr; ptr = rhs.ptr; rhs.ptr = tempPtr; } Array2d& assign(Array2d tmp) { swap (tmp); return *this; } Array2d(const Array2d& a) : zeilen(a.zeilen), spalten(a.spalten), ptr(new T[zeilen*spalten]) { size_t anzahl = zeilen * spalten; for (size_t i=0; i<anzahl; ++i) { ptr[i] = a.ptr[i]; } }Ich kenne mich mit eigenen Operatoren noch nicht aus, deshalb werden hier für eine Zuweisung Methoden benutzt.
Wenn ich, wie man oben siehtb.assign(arr);eingebe, wird der Kopierkonstruktor aufgerufen, alles schön und gut, der Code funktioniert ja auch, aber es gibt eine Sache die ich nicht verstehe..
Der Kopierkonstruktor wird aufgerufen und das Objekt (*this) wird mit den Zeilen und Spalten etc. "initialisiert" :
Array2d(const Array2d& a) : zeilen(a.zeilen), spalten(a.spalten), ptr(new T[zeilen*spalten]) { size_t anzahl = zeilen * spalten; for (size_t i=0; i<anzahl; ++i) { ptr[i] = a.ptr[i]; } }Erst danach geht er komischerweise auf die "assign()"-Methode ein und mein Objekt (*this) hat plötzlich wieder die selben Werte wie vorher und nicht die, die vom Kopierkonstruktor zugewiesen wurden. Meine Fragen :
Ich würde mich über Hilfe freuen, weil ich schon extrem lange hier sitze und immer wieder aufs neue sinnlos Debugge!
-
Du willst beim Assign zwei Dinge:
1. der alte State soll zerstört werden
2. der neue State soll rüberkopiert werden
Das rüberkopieren erledigt der Kopierkonstruktor. Der kopiert die Werte in das Funktionsargument hinein. Nun hat man bereits eine Kopie der Werte. Diese Kopie muss jetzt noch irgendwie in *this landen und die alten Werte zerstört werden. Das geht mit dem idR günstigem swap. Der vertauscht die neuen Werte mit den alten. In *this sind nun die neuen und in tmp die alten. Wenn jetzt die Funktion verlassen wird, wird der Destruktor von tmp aufgerufen, da dass eine lokale Variable ist. Dieser zerstört dann die alten Werte.BTW: Zur Implementierung von swap, kannste std::swap verwenden, da sparst du dir die tmps:
std::swap(zeilen, rhs.zeilen); std::swap(spalten, rhs.spalten); std::swap(ptr, rhs.ptr);
-
Das ist das Copy&Swap-Idiom.
Du uebergibst der Methode assign einen Wert als Kopie (da die Methode keine Referenz annimmt, was hier auch richtig so ist). Das heisst, bevor in die Methode rein gegangen wird, wird der Wert arr in den Wert tmp kopiert. Natuerlich mit dem Kopierkonstruktor! Waehrend dieser Kopie bezieht sich "this" aber auf tmp, da ja der Kopierkonstruktor fuer tmp aufgerufen wird. Erst wenn die Kopie erledigt ist, faengt die assign-Methode an. Dieses wurde aufgerufen fuer das Objekt, auf das sich this nun bezieht. Die Werte haben sich also nicht veraendert, sondern das this bezieht sich auf verschiedene Objekte.