Viele Antworten beziehen sich auf die Art, wie die Referenzzählung gespeichert wird (sie wird in einem gemeinsamen Speicher für alle shared_ptr gespeichert, die denselben nativen Zeiger enthalten), aber die meisten entziehen sich dem Problem von Lecks.
Die einfachste Möglichkeit, Speicher mit Referenzzählern zu verlieren, ist das Erstellen von Zyklen. Als Beispiel wird garantiert, dass eine doppelt verkettete Liste, in der alle Zeiger shared_ptr mit mindestens zwei Elementen sind, nicht gelöscht wird. Selbst wenn externe Zeiger freigegeben werden, werden die internen Zeiger immer noch gezählt, und der Referenzzähler wird 0 nicht erreichen. Das ist zumindest mit der naivsten Implementierung.
Die einfachste Lösung für das Zyklusproblem ist das Mischen von shared_ptr (Referenzzähler) mit schwachen Zeigern, die den Eigentümer des Objekts nicht teilen.
Gemeinsam genutzte Zeiger teilen sich sowohl die Ressource (Zeiger) als auch die zusätzlichen Informationen zu reference_count. Wenn Sie schwache Zeiger verwenden, wird die Anzahl der Referenzen verdoppelt: Es gibt eine gemeinsame Referenz für den Zeiger und eine Referenz für den schwachen Zeiger. Die Ressource wird freigegeben, sobald der Zähler für gemeinsam genutzte Zeiger den Wert 0 erreicht, aber die Information referenz_zählstand bleibt bestehen, bis der letzte schwache Zeiger freigegeben wird.
In der doppelt verketteten Liste wird die externe Referenz in einem shared_ptr gehalten, während die internen Links nur schwach_ptr sind. Wenn keine externen Referenzen (shared_ptr) vorhanden sind, werden die Elemente der Liste freigegeben und die schwachen Referenzen gelöscht. Am Ende wurden alle schwachen Referenzen gelöscht und der letzte schwache Zeiger auf jede Ressource gibt die reference_count-Information frei.
Es ist weniger verwirrend als der obige Text scheint ... Ich werde es später noch einmal versuchen.
Dies ist die korrekteste Antwort. –
Der Ansatz mit verketteten Listen vermeidet die zusätzliche Zuweisung, ist aber ohne globalen Mutex sehr schwierig "Thread-sicher" zu machen. ("thread-safe" wie in "als thread-safe wie ein roher Zeiger") – curiousguy
Auch wenn Sie 'make_shared' verwenden, kann die zusätzliche Zuweisung vermieden werden, indem das zugeordnete Objekt und der Instanzzähler in einem einzelnen Speicherblock abgelegt werden. – Ferruccio