Verständnisfrage
-
Hallo, erst mal sorry für die Überschrift, aber mir ist tatsächlich kein besserer Titel zu dem Thema eingefallen. Ich demonstriere mein Problem mal eben anhand dieser Methoden :
Array2D& assign(Array2D a) { swap(a); return *this; } void swap (Array2D& a) { /* SO AKTZEPTIERT DER COMPILER ALLES _________________________________ size_t temp = zeilen; zeilen = a.zeilen; a.zeilen = temp; temp = spalten; spalten = a.spalten; a.spalten = temp; T* tmp = ptr; ptr = a.ptr; a.ptr = tmp; */ // DAS WÄRE "meine Variante: " zeilen = a.zeilen; spalten = a.spalten; T* tmp = ptr; ptr = a.ptr; a.ptr = tmp; } Array2D(const Array2D& a) : zeilen(a.zeilen), spalten(a.spalten), ptr(new T[a.zeilen*a.spalten]) { const int ANZ = zeilen* spalten; for (size_t i=0; i<ANZ; ++i) { ptr[i] = a.ptr[i]; } } ~Array2D() { delete [ ] ptr; }
Kann mir jemand erklären, wieso ich bei der Methode "swap" die Zeilen und die Spalten an das übergebene Objekt "a" zuweisen muss?
Das a den Pointer von *this übergeben bekommen muss dient ja der "Zerstörung" des alten Speicherplatzes, aber wieso zur Hölle müssen die Zeilen und Spalten auch an "a" zugewiesen werden?
Für den Destruktor ist das doch irrelevant, oder?!
-
"swap" bedeutet "tauschen".
int a = 3; int b = 5; std::swap(a,b); // jetzt gilt: a == 5, b == 3)
-
Lass das swap so wie es war und füge Deinen code ins assign ein und lass dort den Aufruf von swap weg Beim ptr lässt Du die Tauscherei natürlich dann auch weg
swap = tauschen
assign = zuweisenArray2D& assign(Array2D a) { zeilen = a.zeilen; spalten = a.spalten; ptr = a.ptr; return *this; } void swap (Array2D& a) { size_t temp = zeilen; zeilen = a.zeilen; a.zeilen = temp; temp = spalten; spalten = a.spalten; a.spalten = temp; T* tmp = ptr; ptr = a.ptr; a.ptr = tmp; } Array2D(const Array2D& a) : zeilen(a.zeilen), spalten(a.spalten), ptr(new T[a.zeilen*a.spalten]) { const int ANZ = zeilen* spalten; for (size_t i=0; i<ANZ; ++i) { ptr[i] = a.ptr[i]; } } ~Array2D() { delete [ ] ptr; }
-
Bei swap möchtest du doch die beiden Objekte vertauschen! Bei deiner Variante würdest du nur ptr vertauschen und die Spalten und Zeilen nur kopieren.
Kürzer (und damit besser lesbar) wäre also die Variante mittels std::swap (aus der Standard C++ Library):
void swap (Array2D& a) { std::swap(zeilen, a.zeilen); std::swap(spalten, a.spalten); std::swap(ptr, a.ptr); }
Edit: Der Trick beim assign besteht darin, daß dort ein lokales Objekt 'a' (anstatt einer Referenz) benutzt wird, so daß nach dem swap-Aufruf dieses Objekt (in dem nun die Daten des ursprünglichen Objekts stehen) dann zerstört wird (d.h. der Destruktor aufgerufen wird).
PS. Dies nennt sich dann Copy and swap idiom
-
Danke erstmal für die Antworten!
Ich möchte mich direkt auf ein Zitat lehnen, da ich meine Frage vermutlich undeutlich gestellt habe :Bei swap möchtest du doch die beiden Objekte vertauschen! Bei deiner Variante würdest du nur ptr vertauschen und die Spalten und Zeilen nur kopieren.
Das Prinzip ist mir relativ klar, aber das Objekt "a" wird doch ohnehin nachdem "assign" ausgeführt wurde gelöscht. Von daher kann ich nachvollziehen, dass die Pointer vertauscht werden (alter Speicherplatz wird gelöscht ), aber wieso weise ich dem Objekt a noch die Zeilen und Spalten zu, wenn a ohnehin nach assign nicht mehr existiert? Zur Löschung benötige ich doch nur den Pointer (die alte "Startadresse" des Arrays"), oder inwiefern vertue ich mich ?
-
du verwechselst das schon wieder.
"assign" = Zuweisung. Du holst die Werte aus einem anderen Objekt. Das andere Objekt wird anschließend weggeworfen, da copy per value.
"swap" = tauschen. Du tauschst die Werte von zwei Objekten. Das andere Objekt wird daher per Referenz übergeben und existiert nach dem Aufruf weiter.
-
Cre schrieb:
Das Prinzip ist mir relativ klar, aber das Objekt "a" wird doch ohnehin nachdem "assign" ausgeführt wurde gelöscht. Von daher kann ich nachvollziehen, dass die Pointer vertauscht werden (alter Speicherplatz wird gelöscht ), aber wieso weise ich dem Objekt a noch die Zeilen und Spalten zu, wenn a ohnehin nach assign nicht mehr existiert? Zur Löschung benötige ich doch nur den Pointer (die alte "Startadresse" des Arrays"), oder inwiefern vertue ich mich ?
Dein Code, Deine Regeln.
Aber selbst, wenn Duswap()
nur inassign()
aufrufst, finde ich die Benamsung irritierend - einswap()
, dass ein bisschen tauscht...
Wenn Du Deinassign()
mit swap() schreiben willst, dann mitstd::swap
nur auf den SpeicherArray2D& assign(Array2D a) { using std::swap; zeilen = a.zeilen; spalten = a.spalten; swap(ptr, a.ptr); return *this; }
o.ä.
Finde ich persönlich auch nicht sofort ersichtlich, wie und warum da was passiert, aber immerhin.
Deinswap()
sollte aber wirklich komplett tauschen - so dass überall die Invariable "ptr zeigt auf Speicher der Größe spalten*zeilen" gilt. Alles andere wird Dir auf die Füße fallen.MichelRT schrieb:
Array2D& assign(Array2D a) { zeilen = a.zeilen; spalten = a.spalten; ptr = a.ptr; return *this; }
Da ist doch ein double delete vorprogrammiert.