Objekt, das Zeiger auf sich selbst enthalten kann, sinnvolle Destruktoren
-
Hallo Forum, ich habe ein Objekt, das in etwa wie folgt ausschaut:
class obj { private: obj *o1,*o2; }Falls es nötig ist, werden o1 und o2 mit new erzeugt, und erhalten dann so wiederum ein Objekt, wodurch eine Baumstruktur entstehen kann. Es kann auch sein, dass beide Objekte mit NULL belegt bleiben, das wäre dann ein Baumende.
Im Destruktor wird delete für beide Objekte aufgerufen.
Jetzt kann es aber zu Fehlern kommen, vor Allem bei Verwendung lokaler Instanzen.Das Problem ist, dass ein Objekt ja delete für seine Unterobjekte aufruft.
In dem Fall kann aber sein, dass ein Objekt gelöscht wird, auf das ein Anderes Objekt noch zeigt. Dann wird versucht, zweimal den gleichen Speicher zu löschen, wodurch ein Fehler entsteht.
Gibt es einen einfachen Weg, das zu lösen?Meine Gedanken waren:
1. Bei der Erstellung neuer Objekte immer den ganzen Objektbaum mit kopieren. Benötigt aber unnötig Speicherplatz.
2. Ein Referenzzähler, aber das gefällt mir weniger und ich scheitere bei einer einfachen ImplementierungHat jemand noch eine einfache, bessere Idee?
-
Smartpointer. In dem Fall:
http://de.cppreference.com/w/cpp/memory/shared_ptr
-
Becker schrieb:
Das Problem ist, dass ein Objekt ja delete für seine Unterobjekte aufruft. In dem Fall kann aber sein, dass ein Objekt gelöscht wird, auf das ein Anderes Objekt noch zeigt.
Wie soll dies bei einer "echten" Baumstruktur zustande kommen? Ich meine einen Baum macht auch aus das ein Element nicht von zwei Stellen gehalten wird. Ansonsten wäre dies, wenn zyklische Abhängigkeiten ausgeschlossen werden können, ein Fall für einen Smartpointer mit Referenzzählung (z.B. shared_ptr). Ganz davon abgesehen das ich für die Speicherverwaltung egal in welchen Ansatz einen geeigneten Smartpointer empfehlen würde (Dann spart man sich auch das Schreiben eines Destruktors).
-
Danke für die schnellen Antworten.
Ihr habt das richtig erkannt, eine echte Baumstruktur ist es nicht.Über shared_ptr war ich auch schon gestolpert, hatte diese allerdings ausgeschlossen,
da ich nicht mit dem C++11-Standard oder Hilfsbibliotheken programmieren kann.Dann werde ich versuchen, die Funktionalität nachzubilden. Das dürfte wieder einfacher
Referenzzählung recht nahe kommen. Aber wenn es nicht anders geht, bleibt mir wohl keine Wahl.Wenn jemand noch was weiß, gern her damit.
-
Wenn möglich würde dafür sorgen, dass bei der Löschung keine Zeiger mehr auf das Objekt existieren, dann könnte man auch
std::unique_ptroder was Simples selbstgebasteltes verwenden. Oft will man, wenn ein Objekt aus einer Datenstruktur gelöscht wird, es auch wirklich weghaben und seine Lebensdauer nicht künstlich verlängern. Aber ich kenne die konkrete Anwendung zu wenig...Wieso brauchst du also geteilte Besitzverhältnisse?
-
Erfinde eine Klasse, die alle Knoten in einem vector<unique_ptr> besitzt. Dann kannst du die Knoten untereinander verbinden wie du willst und hast gar keine Besitzverhaeltnisse.
-
Becker schrieb:
Über shared_ptr war ich auch schon gestolpert, hatte diese allerdings ausgeschlossen, da ich nicht mit dem C++11-Standard oder Hilfsbibliotheken programmieren kann.
Teste mal trotzdem, ob es std::shared_ptr oder std::tr1::shared_ptr gibt. shared_ptr gab es schon vor C++11, zum Beispiel in VS2010.
-
shared_ptrgibt's auch in der Boost. Die funktionieren sogar mit VC6 und ähnlichen grossväterlichen Compilern.