C++ shared_ptr vs.unique_ptr für die Ressourcenverwaltung
-
21-12-2019 - |
Frage
Ich habe über die Verwendung nachgedacht unique_ptr
vs shared_ptr
vs own_solution
.Letzteres habe ich außer Acht gelassen, da ich mit ziemlicher Sicherheit einen Fehler machen werde, aber ich habe mit beiden ein Problem unique_ptr
Und shared_ptr
darin, dass keiner genau das einfängt, was ich will.Ich möchte einen Ressourcenmanager erstellen, der explizit Eigentümer einer Ressource ist. Ich möchte jedoch, dass der Ressourcenmanager auch Verweise auf die Ressource ausgibt.
Wenn ich es benutze unique_ptr
Im Ressourcenmanager und beim Verteilen von Rohzeigern besteht die Möglichkeit, dass sie an anderer Stelle entkommen könnten (obwohl dies meiner Meinung nach gegen den Klassenvertrag verstoßen würde).Wenn ich es benutze shared_ptr
und austeilen weak_ptr
, nichts hindert einen Anrufer daran, das zu konvertieren weak_ptr
zu einem shared_ptr
und das Speichern, wodurch möglicherweise ein Kreislauf oder schlimmer noch, eine Ressource entsteht, die über die Lebensdauer des Ressourcenmanagers hinaus weiterlebt.Ich vermute also, dass ich nach einer aufschiebbaren Lösung suche weak_ptr
das lässt sich nicht in ein umwandeln shared_ptr
.
Oder möchte ich den Vertrag nur mit einigen stark formulierten Kommentaren im Code durchsetzen?
Vielen Dank für Ihre Gedanken dazu.
Lösung
Intelligente Zeiger mögen shared_ptr
Und unique_ptr
sind ein gutes Werkzeug, wenn Sie haben besitzen Hinweise.
Aber für nicht besitzende Zeiger, d.h. Hinweise beachten, die Verwendung eines rohen Zeigers ist völlig in Ordnung.
Ich denke, in Ihrem Entwurf ist der Ressourcenmanager der einzige „Eigentümer“ der Ressourcen, Sie könnten also einfach eine Art intelligenten Zeiger haben innen der Ressourcenmanager.Beispielsweise kann der Ressourcenmanager eine haben std::vector<std::unique_ptr<Resource>>
als Datenelement oder noch einfacher std::vector<Resource>
wenn dein Resource
Die Klasse ist so konzipiert, dass sie korrekt in a gespeichert werden kann std::vector
.
Dann kann der Ressourcenmanager nur nicht besitzende Beobachtungszeiger nach außen geben, und Rohzeiger (oder C++-Referenzen) sind in diesem Fall in Ordnung.
Natürlich ist es wichtig, dass die Lebensdauer des Ressourcenmanagers die der „Ressourcenclients“ überschreitet.
Andere Tipps
Letztlich kann man niemanden zwingen, zuzuhören.Fragen Sie bei Microsoft, Apple oder einem anderen Open-Source-Bibliotheksentwickler, sie alle kennen diesen Song.Ein Kommentar in den richtigen Worten und an der richtigen Stelle ist die beste Wahl.
Vermeiden Sie die Erstellung einer eigenen Smart-Pointer-Klasse, da dies die Komposition behindert und die Lesbarkeit verringert.Versuchen Sie als letzten Ausweg, in Boost oder einem anderen Framework zu suchen, mit dem Ihr Code bereits arbeiten muss.
Wenn Sie Nichteigentümer haben, sind diese entweder zum Halten wählbar weak_ptr
s oder (sofern garantiert, dass sie für die Dauer gültig bleiben) Rohzeiger.
Wenn du benutzt shared_ptr
s intern (warum sollten Sie), am besten bereitstellen weak_ptr
und rohe Hinweise.
Alle diese intelligenten Zeiger bezeichnen ausdrücklich eine Eigentumsrichtlinie.Rohzeiger bedeuten „keine“ oder „nicht besitzende“ Zeiger.
auto_ptr
:Nicht verwenden, da es selbst für Vorsichtige zu viele Fallen gibt.unique_ptr
:Alleineigentum.shared_ptr
:Geteilter Besitzweak_ptr
:Kein Eigentum, könnte hinter Ihrem Rücken gelöscht werden.- roher Zeiger
- Ausdrücklich kein Eigentum mit garantierter längerer Lebensdauer
- oder manuelle Eigentumsverwaltung.
Also nehme ich an, was ich suche, ist ein verschiebbares schwaches_ptr kann nicht in ein Shared_PTR konvertiert werden.
Sie können Ihre einzelnen Helfer-Klasse ausgeben:
generasacodicetagpre.Dies ist etwas besser als ein RAW-Zeiger, da Sie überprüfen können, ob Ihr Zeiger noch gültig ist.
Beispielnutzung:
generasacodicetagpre.Es kann jedoch ein Benutzer es jedoch immer noch mit dem generationspflichtigen Genuss missbrauchen, aber es dauert etwas mehr kriminelle Energie.