operator überladen, aber welchen?
-
Hi,
wenn ich eine Klasse definieren..
class MyClass { public: MyClass( const int a = 0 ) { p = new double; setValue( a ); } ~MyClass() {delete p; } void setValue( const int a ) const { *p = a; } void printValue() const { cout << *p << endl; } private: double* p; };dann kann ich das machen...
int main... { ... MyClass a(2); MyClass b(12); a.printValue(); b.printValue(); ... return 0; }wenn aber b = a; dann bekomme ich
*** glibc detected *** double free or corruption (fasttop):
Ok. Wenn b = a; dann zeigen (weil die Zuweisung vom Compiler generiert wird und deshalb in diesem Fall fehlerhaft) a.p und b.p auf denselben Speicher.
Das führt dann zu dem oben genannten Fehler.Abhilfe:
MyClass& operator=( const MyClass& a) { if( *this != &a ) { delete p; p = new double; *p = *a.p; } return *this; }Der operator nimmt also eine "read-only" Referenz auf der rechten Seite der Zuweisung, da wir nur die linke Seite ändern müssen.
Jetzt sollten a.p und b.p nicht mehr auf den gleichen Speicherbereich zeigen.
Jo, alles läuft.Aber wenn ich
MyClass* a = new MyClass(2); MyClass* b = new MyClass(12); a->print(); b->print(); b = a;ich bekomme
*** glibc *** detected invalid pointer
ich kann ja nicht den Operator von oben nehmen. Was muss ich überladen, damit die Zuweisung klappt?
Gruß
-
so ganz verstehe ich dich nicht. Du schreibst doch erst, dass alles läuft. Dann schreibst du, dass derselbe Code auf einmal nciht mehr läuft? Oder habe ich da etwas übersehen?
Was mir aber noch aufgefallen ist:
if( *this != &a )hier stimmt definitiv etwas nicht. überlege dir mal, was genau du hier vergleichst..
achso, und diese Zeile wird auch nicht funktionieren:
*p = *a.p;Arrays können nicht per Zuweisung kopiert werden.
-
FrankTheFox schrieb:
MyClass* a = new MyClass(2); MyClass* b = new MyClass(12); a->print(); b->print(); b = a;ich bekomme
*** glibc *** detected invalid pointer
Du weist hier ein Pointer einem anderen zu. Das heißt, a und b zeigen hinterher auf das selbe MyClass-Objekt, nämlich auf das mit der 12. Auf das mit der 2 gibts nach der Zuweisung keinen Pointer mehr, du hast es aber auch nicht zerstört. Es hängt also auf ewig im Speicher rum (wenn nicht das Bestriebssystem so lieb wäre, den irgendwann wieder freizugeben). Nennt sich Speicherleck und ist Grund für die Fehlermeldung. Hat aber rein garnichts mit den Operatoren von MyClass zu tun.
-
Hi,
jupp, hier sollte
if( this != &a )stehen.
Ich nutze keine Array's. Hier steht doch nur ein Zeiger auf ein double.
Ja! Wenn ich
MyClass a(2); MyClass b(12); ... a=b;dann stimmt's *b.p hängt planlos in Raum (unerreicht)
weil b.p zeigt auf die gleiche Speicherstelle wie a.p. Wobei in diesem Fall...uppsnicht nur *b.p == *a.p sondern sogar b.p == a.p.
Tjo, dass sollte der operator richten...
Wenn ich aber die Objekte a und b über new erzeuge, dann funktioniert doch der
Zuweisungsoperator nicht mehr. Wie kann ich denn dann a = b machen?
-
FrankTheFox schrieb:
Ich nutze keine Array's. Hier steht doch nur ein Zeiger
ähm... *ups*... ja, hast natürlich recht. Ist wohl doch noch zu früh

Es geht dir hier doch nur ums Prinzip, das ist kein "ernst gemeinter" Code?
-
Nö,
nur ein Beispiel um zu sehen was ich machen muss wenn:
A) Objektinstanz auf dem Heap
Objektinstanz statisch durch Variablen dekl. ( ohne new )für
habe ich eine Lösung ( und ich denke auch verstanden
)
aber für A) nicht.
-
A) Smartpointer. Welcher genau, kommt auf deine Anforderung an (unique, Referenzzählung, ...)
-
Meinst Du jetzt die Zuweisung?
Naja, bei b) weist Du ja objektA = objektB. Dasselbe musst Du bei a) auch machen. Und um aus einem Zeiger ein Objekt zu machen, gibt es den Stern-Operator. Sprich, (*zeigerA) ergibt objektA.
Ergo: Du weist zwei Objekte immer einander gleich zu, durch a = b. Wenn a ein Zeiger ist, musst Du aus a ein Objekt machen (dereferenzieren).
-
Ok.
also muss ich:
MyClass* operator=( const MyClass* a) ...sowas machen? Oder bin jetzt komplett neben der Spur?
-
Nein, die Zuweisung geht immer gleich vonstatten, nämlich von Objekt zu Objekt. Es gibt nur den einen operator=(Objekt const& other) für die Kopie.
Du musst nur beim Zuweisen darauf achten, zwei Objekte zu haben.
Object a; Object b; // Objekte a = b; // Muster: OBJEKT = OBJEKT Object* a; Object* b; // Zeiger // Das Objekt, auf das a zeigt, ist "*a" // Das Objekt, auf das b zeigt, ist "*b" // Übung: Kombiniere das Muster OBJEKT = OBJEKT und das Wissen, wie man aus Zeigern Objekte macht
-
Was Du beobachtest ist, was schief gehen kann, wenn man die 3er-Regel nicht beachtet. Es fehlt Dir nicht nur ein Zuweisungsoperator sondern auch ein Kopierkonstruktor.
FrankTheFox schrieb:
MyClass& operator=( const MyClass& a) { if( this != &a ) { delete p; p = new double; *p = *a.p; } return *this; }Das ist leider nicht Ausnahme-sicher. new kann in die Hose gehen, in welchem Fall die Funktion verlassen wird, ohne, dass *this in einem gültigen Zustand ist.
FrankTheFox schrieb:
Aber wenn ich
MyClass* a = new MyClass(2); MyClass* b = new MyClass(12); a->print(); b->print(); b = a;ich bekomme
*** glibc *** detected invalid pointer
ich kann ja nicht den Operator von oben nehmen. Was muss ich überladen, damit die Zuweisung klappt?
WTF?! Das sind normale, rohe Zeiger. Du kannst die Bedeutung des Zuweisungsoperators für rohe Zeiger nicht ändern. Die Zuweisung führt hier zu einem Speicherleck. Ich sehe nirgens ein delete, was zu der Fehlermeldung führen könnte.
So macht man das:
class indirect_int { // Invariante: ptr zeigt immer auf ein // gueltiges int-Objekt. int* ptr; public: indirect_int(int i=0) : ptr(new int(i)) {} ~indirect_int() { delete ptr; } indirect_int(indirect_int const& x) // copy ctor : ptr(new int(*x.ptr)) {} void swap(indirect_int & that) { std::swap(this->ptr,that.ptr); } indirect_int& operator=(indirect_int temp) // copy assign { this->swap(temp); return *this; } // per "copy & swap"-Trick int value() const { return *ptr; } void value(int newv) { *ptr = newv; } }; inline void swap(indirect_int & a, indirect_int & b) { a.swap(b); }
-
LordJaxom schrieb:
// Übung: Kombiniere das Muster OBJEKT = OBJEKT und das Wissen, wie man aus Zeigern Objekte machtHi, wieder do. Also wenn ich dich richtig verstanden habe muss das dann so gehen.
MyClass* a = new MyClass(2); MyClass* b = new MyClass(12); a->print(); b->print(); *b = *a; b->print(); delete a; delete b;krümelkacker schrieb:
WTF?! Das sind normale, rohe Zeiger. Du kannst die Bedeutung des Zuweisungsoperators für rohe Zeiger nicht ändern. Die Zuweisung führt hier zu einem Speicherleck. Ich sehe nirgens ein delete, was zu der Fehlermeldung führen könnte.
Mein Fehler:
wenn der Code (statische Objekterstellung) ausgeführt wird kommt ohne Zuweisungoperator wohl ein glibc aberr ich habe die glibc's durcheinander gebracht:*** glibc detected *** /home/blabla : double free or corruption (fasttop)...
Tjo, stimmt der new kann in die Hose gehen.
Gruß
-
--