Wie funktioniert weak_ptr?
Ich verstehen, wie weak_ptr
und shared_ptr
. Ich verstehe, wie shared_ptr
Werke, durch zählen der Anzahl von Referenzen in Ihrem Objekt. Wie funktioniert weak_ptr
Arbeit? Ich habe versucht, das Lesen durch die boost-source-code, und ich bin nicht vertraut genug mit boost zu verstehen, all die Dinge, die Sie verwendet.
Dank.
Kommentar zu dem Problem
Siehe auch: Wie kann shared Pointer arbeiten?
Siehe auch shared_ptr implementation notes
InformationsquelleAutor der Frage Oliver Zheng | 2011-04-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
shared_ptr
verwendet eine extra "counter" - Objekt (aka. "shared count" oder "control Blocks"), die zum speichern der Referenz-count.(BTW: das "counter" - Objekt speichert auch die deleter.)
Jeder
shared_ptr
undweak_ptr
enthält einen Zeiger auf die tatsächlichen pointee, und eine zweiten Zeiger auf das "counter" - Objekt.Umzusetzen
weak_ptr
, die "counter" - Objekt speichert zwei unterschiedliche Zähler:shared_ptr
Instanzen verweisen auf das Objekt.weak_ptr
Instanzen verweist auf das Objekt, plus eins, wenn die "Anzahl" ist immer noch > 0.Den pointee wird gelöscht, wenn der "Anzahl" den Wert null erreicht.
"Counter" Helfer Objekt wird gelöscht, wenn die "schwachen zählen" null erreicht (das heißt, die "Anzahl" auch null sein, siehe oben).
Wenn Sie versuchen, erhalten Sie eine
shared_ptr
aus einerweak_ptr
, die Bibliothek atomar prüft die "use count", und wenn es > 0 Schritten. Wenn das gelingt, bekommen Sie Ihreshared_ptr
. Wenn der "Anzahl" war schon gleich null, Sie bekommen eine leereshared_ptr
Instanz statt.BEARBEITEN: Nun, warum tun Sie hinzufügen, um den schwachen zu zählen, anstatt nur die Freigabe der "Zähler" - Objekt, wenn beide zählt auf null fallen? Gute Frage.
Die alternative wäre, löschen Sie die "counter" - Objekt, wenn sowohl die "use count" und die "schwachen count" auf null fallen. Hier der erste Grund ist: Überprüfung von zwei (pointer, size) Zähler atomar ist nicht möglich auf jeder Plattform, und selbst dort, wo es ist, es ist komplizierter, als die überprüfung nur einen Zähler.
Ein weiterer Grund ist, dass der deleter muss bleiben gültig, bis Sie beendet die Ausführung. Seit der deleter ist gespeichert in der "Zähler" - Objekt, das bedeutet, dass die "counter" - Objekt muss bleiben gültig. Betrachten Sie, was passieren könnte, wenn es eine
shared_ptr
und eineweak_ptr
auf einen Gegenstand, und Sie werden gleichzeitig zurückgestellt und der gleichzeitigen threads. Lassen Sie uns sagen, dieshared_ptr
kommt zuerst. Es verringert die "Anzahl" auf null und beginnt mit der Ausführung der Streicher. Jetzt dieweak_ptr
verringert die "schwachen count" auf null, und findet die "use count" null ist als auch. So löscht Sie die "counter" - Objekt, und mit ihm der Streicher. Während der deleter ist, der noch läuft.Natürlich gäbe es verschiedene Möglichkeiten, um sicherzustellen, dass die "counter" - Objekt bleibt lebendig, aber ich denke, dass die Erhöhung der "schwachen zählen" ist eine sehr elegante und intuitive Lösung. Die "schwachen zählen", wird der Verweiszähler für die "counter" - Objekt. Und da
shared_ptr
s Referenz der Zähler, Objekt zu, auch Sie haben, erhöhen Sie die "schwachen zählen".Wohl noch mehr intuitive Lösung wäre, erhöhen Sie die "schwachen count" für jedes einzelne
shared_ptr
, da jedes einzelneshared_ptr
halten, ist ein Verweis auf die "counter" - Objekt.Hinzufügen einer für alle
shared_ptr
Instanzen ist nur eine Optimierung (spart atomaren Inkrement/Dekrement, wenn das kopieren/zuweisen vonshared_ptr
Instanzen).InformationsquelleAutor der Antwort Paul Groke
Grundsätzlich ein "weak_ptr" ist eine ganz normale "T*" - Zeiger, mit der Sie die WIEDERHERSTELLUNG einer starken Referenz, d.h. "shared_ptr", später in den code.
Nur wie ein normaler T*, die weak_ptr-nicht reference-counting. Intern, zur Unterstützung der reference-counting auf einen beliebigen Typ T, der STL (oder jede andere Bibliothek der Umsetzung dieser Art von Logik) erzeugt ein wrapper-Objekt, das wir nennen "Anker". "Anker" vorhanden, die ausschließlich zur Umsetzung der reference count und "wenn count gleich null ist, rufen Sie "löschen" Verhalten, das wir brauchen.
In eine starke Referenz, die shared_ptr implementiert seine Kopie, operator=, Konstruktor, Destruktor, und andere relevante APIs aktualisieren "Anker"'s reference count. Dies ist, wie ein shared_ptr sorgt dafür, dass Ihr "T" lebt genau so lange, wie jemand es zu benutzen. In einem "weak_ptr", die die gleichen APIs, kopieren Sie einfach die tatsächliche Anker ptr herum. Sie werden NICHT aktualisiert, Referenz zählt.
Dies ist der Grund, warum die wichtigsten APIs der "weak_ptr" sind "abgelaufen" und die schlecht mit dem Namen "lock". "Abgelaufen", sagt Sie, wenn das zugrunde liegende Objekt ist immer noch da - also "Hat es bereits selbst gelöscht, weil alle starken Referenzen ging aus dem Rahmen?". "Lock" wird (wenn er kann) konvertieren Sie die weak_ptr-zu einer starken Referenz shared_ptr, wiederherstellen reference-counting.
BTW, "lock" ist ein schrecklicher name für die API. Sie sind nicht (nur) auf ein mutex, du bist die Schaffung einer starken Referenz aus einem schwachen, mit "Anker" fungieren. Der größte Fehler in beiden Vorlagen ist, dass Sie nicht implementiert operator->, so zu tun, etwas mit Ihrem Objekt, das Sie wiederherstellen, die raw - "T*". Sie Taten dies meist zur Unterstützung von Dingen wie "shared_ptr", weil die primitiven Typen nicht unterstützen "->" operator.
InformationsquelleAutor der Antwort user3726672