Volkards Kurs Lektion 63: this (Frage dazu)
-
Volkards Kurs schrieb:
Hier wird im Zuweisungsoperator
void operator=(const Vector &derAndereVector) { delete[] m_data; m_size=derAndereVector.m_size; m_data=new double[m_size]; for(int i=0;i<m_size;++i) m_data[i]=derAndereVector.m_data[i]; };
zuerst der Speicherbereich von v1.m_data gelöscht und dann neu angelegt. Dann wird der Speicher von v1.m_data auf sich selbst kopiert. Die Schleife hat also keine Wirkung. Die Daten, die vorher im Vector standen sind verloren.
Wieso wird der auf sich selbst kopiert? Versteh ich nicht.
Erst wird m_data gelöscht, dann size vom anderen Vector übernommen und damit dann m_data wieder neugemacht. Und dann sehe ich da, dass die Daten normal übernommen werden. Wieso kopiert der sich denn dann auf sich selbst?Bitte erklärts mir einer!
Mr. B
-
Geht es da vielleicht um Selbstzuweisung?
-
Moment, ich kopier die Lektion am besten zu Ende (fängt genau dort an, wo das obere Zitat aufgehört hat):
Volkards Kurs schrieb:
Überprüfen Sie im Zuweisungsoperator immer auf Zuweisungen an sich selbst!
Um diese Überprüfung möglich zu machen, gibt es den Zeiger this. Dieser Zeiger ist in jeder Methode vorhanden und zeigt auf das aktuelle Objekt. Sie könnten also z.B. statt
int getSize() { return m_size; };
ebenso schreiben:
int getSize() { return this->m_size; };
Wenn zwei Zeiger auf genau den selben Speicherbereich zeigen, dann zeigen sie auf dasselbe Objekt. Mit dem this-Zeiger ist es also möglich, zu überprüfen, ob die übergebene Referenz auf das aktuelle Objekt zeigt. Man braucht ihn nur mit der Adresse des anderen Vectors zu vergleichen. Nur wenn diese beiden Adressen unterschiedlich sind, muß der Zuweisungsoperator eine richtige Kopie anlegen, anderenfalls hat er nichts zu tun.
void operator=(const Vector &derAndereVector) { if(&derAndereVector!=this) { delete[] m_data; m_size=derAndereVector.m_size; m_data=new double[m_size]; for(int i=0;i<m_size;++i) m_data[i]=derAndereVector.m_data[i]; }; };
(r) by Volkard
mit anderen Worten: JA...
-
Überprüfen Sie im Zuweisungsoperator immer auf Zuweisungen an sich selbst!
Na siehst du. Es geht also um Selbstzuweisung.
Wenn jetzt also this == &derAndereVector gilt, dann tritt genau ein, was Volkard geschrieben hat.
Eine Lösung steht in dem Beitrag auch schon (zwischen den Zeilen).Eine andere Möglichkeit (ohne Test auf Selbstzuweisung):
Vector& operator=(const Vector &derAndereVector) { double* temp = new double[derAndereVector.m_size]; copy(derAndereVector.m_data, derAndereVector.m_data + derAndereVector.m_size, temp); m_size=derAndereVector.m_size; swap(temp, m_data); delete [] temp; return *this; }
-
Ohhhhh... vielleicht sollte ich mal auf den Code gucken, da steht ja
v1 = v1
Dann ist der Rest klar, aber was soll diese Zuweisung bezwecken?
Was erreicht man, wenn man sowas schreibt? Den Nutzen davon hab ich nicht kapiert.Mr. B
-
Mr. B schrieb:
Ohhhhh... vielleicht sollte ich mal auf den Code gucken, da steht ja
v1 = v1
Dann ist der Rest klar, aber was soll diese Zuweisung bezwecken?
In der Regel wird niemand sowas wie v1 = v1 schreiben. Im Zuge von Aliasing (mehrere Namen für ein und das selbe Objekt - Stichwort: Referenzen, Zeiger)kann eine Selbstzuweisung aber durchaus mal vorkommen. In diesem Fall muss dein op= sicherstellen, dass das Ergebnis das ist, was man erwartet (v1 hat nachher den selben Wert wie vorher).
Eine Möglichkeit um dies sicherzustellen ist der genannte Test auf this == &other. Eine andere sehr verbreitete Möglichkeit (die außerdem noch Exception-Sicher ist), ist das Copy&Swap-Idiom.
-
HumeSikkins schrieb:
Eine andere sehr verbreitete Möglichkeit (die außerdem noch Exception-Sicher ist), ist das Copy&Swap-Idiom.
die ist so verbreitet, weil sie einfach besser ist.
swap braucht man eh, um zwei Vectors krass schnell vertauschen zu können.
void swap(Vector &derAndereVector){ std::swap(m_size,derAndereVector.m_size); std::swap(m_data,derAndereVector.m_data); }
und wenn man das hat und den copy-konstruktor, dann kann man damit einen coolen zuweisungsoperator basteln.
Vector& operator=(Vector const& derAndereVector){ Vector kopie(derAndereVector); swap(kopie); return *this; //edit: siehe bashars kommentar }
dauert aber ein welichen, bis man alle tricks durchschaut hat, die dabei benutzt werden.
-
Den Trick das return *this wegzulassen, kannte ich noch gar nicht
(SCNR)