Beinhaltet List-Container Objekte oder Referenzen?
-
Hallo
habe folgendes Problem:
Ich fülle einen List-Container mit Objekten einer selbst definierten Klasse, welches wiederrum von einer weiteren Klasse abgeleitet ist:
... MyClass testObject; list<MyClass> listeVonMyClass; listeVonMyClass.push_back(testObject);Nur leider erhalte ich ein "double free or corruption (fasttop)".
Nun habe ich bei jedem Konstruktor, Dekonstruktor und Copykonstruktor entsprechend eine Ausgabezeile eingefügt per cout. Nun musste ich feststellen, dass beim Ende des Programms mehr Dekonstruktoren aufgerufen werden als Konstruktoren im Programm. Wie kann das sein?
Es sieht so aus als würde die Liste keinen Konstruktor beim Einfügen eines Objektes aufrufen. Das spricht dafür, dass die Liste nur Referenzen speichert. Nur leider scheint die Liste am Programmende die Dekonstruktoren der Objekte aufzurufen. Auch der Copy-Konstruktor meiner Klasse wird beim Einfügen in die Liste nicht aufgerufen.
Irgendeine Idee?Gruß
Gustav
-
Hallo,
Es werden keine Referenzen gespeichert sondern Kopien. Evtl. nutzt deine Implementation den Zuweisungsoerator (CopyAssignment).
-
Da habe ich mich soch tatsächlich verschrieben. Ich meine natürlich, dass die Zuweisungs-Funktions beim Einfügen der Objekte in die Liste nicht aufgerufen werden. Einen Kopier-Konstruktor habe ich gar nicht implementiert. Liegt da das Problem?
-
Ja.
Übrigens, es heißt Destruktor und nicht Dekonstruktor.
-
Gustav Hummel schrieb:
...Einen Kopier-Konstruktor habe ich gar nicht implementiert. ...
<=>
Gustav Hummel schrieb:
...
Nun habe ich bei jedem ... Copykonstruktor entsprechend eine Ausgabezeile eingefügt per cout....
Wenn ein "flache Kopie" nicht GENAU das ist, was Du willst, reicht der implizit erzeugte CopyCtor nicht aus (und die Ausgabe einer Textzeile übernimmt der auch nicht für Dich). Da Du anscheinend mit dynamischem Speicher arbeitest, sieht es sehr danach aus, als ob das Dein Problem sei.
Gruß,
Simon2.
-
Ok Danke. hab mich gleich dran gemacht die Copy-Konstruktoren zu implementieren. Bin aber auf folgendes gestoßen:
MyClass::MyClass(const MyClass &newObject) { m_myTestInt = newObject.m_myTestInt; m_myOtherObject = newObject.m_myOtherObject; // <- bringt Fehlermeldung } MyClass &MyClass::operator=(MyClass &newObject) { if(this != &newObject) { m_myTestInt = newObject.m_myTestInt; m_myOtherObject = newObject.m_myOtherObject; // <- bringt Fehlermeldung } return *this; }Fehlermeldung:
error: no match for ‘operator=’ in ...
Doch in der Zuweisungsmethode funktioniert genau das ohne Fehlermeldung des Compilers. m_myOtherObject besitzt einen selbst implementierten = Operator (getestet und geht auch). Muss ich im Copy-Konstruktor etwas spezielles beachten?
Gruß
Gustav
-
Korrektur:
MyClass::MyClass(const MyClass &newObject) { m_myTestInt = newObject.m_myTestInt; m_myOtherObject = newObject.m_myOtherObject; // <- bringt Fehlermeldung } MyClass &MyClass::operator=(MyClass &newObject) { if(this != &newObject) { m_myTestInt = newObject.m_myTestInt; m_myOtherObject = newObject.m_myOtherObject; // <- bringt !!keine!! Fehlermeldung } return *this; }
-
welchen Typ hat denn m_myOtherObject ?
Gustav Hummel schrieb:
...m_myOtherObject besitzt einen selbst implementierten = Operator ...
Glaub' ich nicht !

Wenn, dann hat die Klasse einen operator=() ...Hast Du vielleicht mit einer forward-deklaration gearbeitet ?
hmmm ...Gruß,
Simon2.
-
Schreib doch mal die ganze Fehlermeldung hin.
-
Simon2 schrieb:
welchen Typ hat denn m_myOtherObject ?
Gruß,
Simon2.
Hallo,
genau ich arbeite mit dynamischen Speicher... m_myOtherObject ist vom eigenen Typ MyDynamicClass. Und genau hier nutze ich dynamisches Speicher. In der Klasse MyDynamicClass sind nun Konstruktor, Destruktor, Copy-Konstruktor und Zuweisungsoperator vorhanden bzw. selbst implementiert.
-
Braunstein schrieb:
Schreib doch mal die ganze Fehlermeldung hin.
Komplette Fehlermeldung:
Severity and Description Path Resource Location Creation Time Id
error: no match for ‘operator=’ in ‘((MyClass*)this)->MyClass::m_myOtherObject = newMyClass->MyClass::m_myOtherObject’ TestProjekt myClass.cpp line 46 1182246184643 2815
-
Hilfreich wäre auch die Fehlermeldung. Aber ich rate mal: Es liegt am const. Dein op= nimm (warum auch immer keine const-Referenz), wenn das beim anderen op= genauso ist, dann kann er im Copy-Konstruktor (der ja ne const-referenz nimmt) nicht verwendet werden.
-
Hallo Jester,
die Fehlermeldung findest du in meinem letzten Beitrag. Vielleicht hilft es, wenn ich noch Copy-Konstruktor und Zuweisungsfunktion der myDynamicClass Klasse poste:
MyDynamicClass &MyDynamicClass::operator=(MyDynamicClass &newMyDynamicClass) { cout << "Zuweisung MyDynamicClass" << endl << flush; // is new object the same object? if(this != &newMyDynamicClass) { // free memory if(m_puiData != NULL) { delete [] m_puiData; } // copy data m_uiStartAddress = newMyDynamicClass.m_uiStartAddress; m_uiLength = newMyDynamicClass.m_uiLength; m_puiData = new uint16_t[m_uiLength]; for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy) { m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy]; } } return *this; } MyDynamicClass::MyDynamicClass(const MyDynamicClass &newMyDynamicClass) { // copy data m_uiStartAddress = newMyDynamicClass.m_uiStartAddress; m_uiLength = newMyDynamicClass.m_uiLength; m_puiData = new uint16_t[m_uiLength]; for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy) { m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy]; } }
-
Ich würde dir raten, den Zuweisungsoperator über den CopyCtor zu implementieren (spart Schreibarbeit, nutze swap) und bei beiden den Parameter als const Referenz zu übernehmen.
Das flush nach dem endl ist auch zuviel. endl mach schon selbst ein flush.
-
Danke für die Tipps. Funktioniert jetzt auch.
Meintest du so?:
MyDynamicClass &MyDynamicClass::operator=(const MyDynamicClass &newMyDynamicClass) { cout << "Zuweisung MyDynamicClass" << endl; // is new object the same object? if(this != &newMyDynamicClass) { // free memory if(m_puiData != NULL) { delete [] m_puiData; } // copy data MyDynamicClass(newMyDynamicClass); } return *this; }Gruß
Gustav
-
Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:
MyDynamicClass const& operator=(MyDynamicClass const& other) { MyDynamicClass tmp(other); tmp.swap(*this); return *this; }
-
EDIT: jetzt überflüssig.
-
Jester schrieb:
Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:
MyDynamicClass const& operator=(MyDynamicClass const& other) { MyDynamicClass tmp(other); tmp.swap(*this); return *this; }ich müsste also lediglich eine swap funktion implementieren mit folgendem code:
std::swap(m_uiStartAddress, src.m_uiStartAddress); std::swap(m_puiData, src.m_puiData); std::swap(m_uiLength, src.m_uiLength)(also alle Elemente tauschen)
Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?
Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?
Gruß
Gustav
-
Gustav Hummel schrieb:
ich müsste also lediglich eine swap funktion implementieren mit folgendem code:
std::swap(m_uiStartAddress, src.m_uiStartAddress); std::swap(m_puiData, src.m_puiData); std::swap(m_uiLength, src.m_uiLength)(also alle Elemente tauschen)
Ja genau.
Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?
Ganz genau. Und das ist auch der große Vorteil davon: Es ist Exception-sicher. Stell Dir vor bei Deiner alten Version klappt zwar das freigeben, aber beim Speicher anfordern (oder Objekte kopieren) fliegt eine Exception. Dann sind Deine alte Daten weg und die neuen kriegste nicht konstruiert. Dein Zustand ist undefiniert. Hier ist es so, dass zunächst der Copy-Konstruktor alle gefährlichen Sachen macht. Fliegt dabei eine Exception ist Dein Objekt noch unverändert. Dann kommt swap, aber das macht nur ungefährliche Sachen, da kann nix fliegen (zumindest sollte man's so implementieren). Danach ist Dein Objekt im neuen Zustand.
Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?
Ich mach das immer so. Aber letztlich ist es egal.

-
Hi,
Gustav Hummel schrieb:
...
Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?...Also ich habe mir das auch angewöhnt, weil man dann mit komplizierteren "const"-trukten (
) besser klarkommt.Ich merke mir immer "const wirkt rückwärts":
char const * a; // Zeiger veränderbar, chars NICHT char * const b; // Zeiger NICHT veränderbar, chars schon char const * const c; // Zeiger NICHT veränderbar, chars auch NICHT ... const char * d; // aus historischen Gründen identisch mit char const *Spätenstens bei Funktionspointern wird es ziemlich schnell unübersichtlich, weswegen ich eine einheitliche Schriftweise bevorzuge.
Gruß,
Simon2.