Im ersten Teil dieses Artikels beschrieb ich das einfache Zählen der Referenzen, mit der man unreferenzierte Objekte erkennen und löschen kann. Objekte können sich jedoch zyklisch referenzieren und so kann es referenzierte aber dennoch unerreichbare Objekte geben, die durch einfaches Zählen der Referenzen nicht zu entdecken sind.
In diesem Teil beschreibe ich, wie man die zyklischen Referenzen in bestimmten Situationen vermeiden kann und so das Problem umgehen kann.
C++ bietet standardmäßig keine automatische Speicherverwaltung. C++ ermöglicht die Verwaltung von dynamischem Speicher unter anderem mit den Operatoren new und delete. Objekte, die mit new angelegt werden, müssen mit delete explizit freigegeben werden.
Als kleine Übung in C++ habe ich eine einfache Garbage Collection implementiert. Sie hat nicht alle Fähigkeiten der Speicherverwaltung von Java oder von C#, dass würde den Rahmen einer Übung sprengen, dafür ist sie aber ziemlich einfach und erfüllt die für mich wichtigste Aufgabe einer Garbage Collection – die nicht erreichbaren Objekte zu löschen.
Wenn ich das
Observer Pattern
in C++ implementieren möchte, brauche ich einen Container, in dem das Subjekt die Pointer
auf die Observer verwaltet. Auf diesen Container habe ich folgende Anforderungen:
Hier eine einfache Lösung. Bag ist ein Contaier, das während der Iteration modifiziert werden kann. Herausgenommene Elemente bekommen garantiert keine Nachrichten mehr. Reihenfolge, in der die Iteration stattfindet ist nicht deffiniert.
Obwohl man in dem Container nicht nach den Elementen suchen kann, passiert das Einfügen und Rausnehmen der Elemente in konstanter Zeit. Jedes Eingefügte Element bekommt nämlich ein „Abo“ das seine Position in dem Container bestimmt. Um aus dem Container herausgenommen zu werden, muss das „Abo“ abbestelt werden. Ein Element könnte auch mehrfach in einem Bag vorhanden sein, dann würde es jede Nachricht mehrfach bekommen.
Die Quelltexte kann man hier downloaden. Um Bag zu benutzen,
sind nur die Dateien bag.cpp und bag.h nötig. Die anderen Quelltexte beinhalten
die gebraucheten Unit-Tests. Um die kompilieren zu können, braucht man das Testframework
CppUnit
Die Quelltexte sind Open Source (BSD-Lizenz)