Welche Art von Zeiger verwende ich Wann?
Ok, also das Letzte mal schrieb ich " C++ für ein Leben std::auto_ptr
war alle std-lib zur Verfügung hatte, und boost::shared_ptr
war in aller Munde. Ich sah nie wirklich in die anderen smart-pointer-Typen-boost zur Verfügung. Ich verstehe, dass C++11 bietet jetzt einige der Arten boost kam mit, aber nicht alle von Ihnen.
Also hat jemand einen einfachen Algorithmus, um zu bestimmen, Wann die smart-pointer? Vorzugsweise einschließlich Beratung in Bezug auf dumb Pointer (raw-Zeigern wie T*
) und der rest der boost smart Pointer. (So etwas wie diese wäre toll).
Siehe auch std::auto_ptr std::unique_ptr
Ich hoffe wirklich, jemand kommt mit einem schönen handlichen Flussdiagramm wie diese STL-Flussdiagramm zur Auswahl.
Oh, das ist wirklich ein schöner! Ich FAQized.
Das ist nicht mal in der Nähe ein Duplikat. Die verlinkten Frage sagt "Wann soll ich mit einer smart-pointer", und diese Frage ist "Wann muss ich mit diese smart Hinweise?", D. H. dieses ist die Einordnung der verschiedenen Einsatzmöglichkeiten des standard-smart-Pointer. Die verlinkte Frage ist dies nicht. Der Unterschied ist scheinbar klein, aber es ist ein großes.
Ich hoffe wirklich, jemand kommt mit einem schönen handlichen Flussdiagramm wie diese STL-Flussdiagramm zur Auswahl.
Oh, das ist wirklich ein schöner! Ich FAQized.
Das ist nicht mal in der Nähe ein Duplikat. Die verlinkten Frage sagt "Wann soll ich mit einer smart-pointer", und diese Frage ist "Wann muss ich mit diese smart Hinweise?", D. H. dieses ist die Einordnung der verschiedenen Einsatzmöglichkeiten des standard-smart-Pointer. Die verlinkte Frage ist dies nicht. Der Unterschied ist scheinbar klein, aber es ist ein großes.
InformationsquelleAutor sbi | 2012-01-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Miteigentum:
Die
shared_ptr
undweak_ptr
die Norm sind so ziemlich das gleiche wie Ihre Boost-Pendants. Verwenden Sie Sie, wenn Sie brauchen, um eine Ressource teilen und nicht wissen, welche die letzten sein werden, um lebendig zu sein. Verwendenweak_ptr
zu beobachten, die freigegebene Ressource, ohne dass die Lebensdauer nicht zu brechen Zyklen. Zyklen mitshared_ptr
sollte normalerweise nicht passieren - zwei Ressourcen, die nicht eigenen jeder andere.Beachten Sie, dass Boost bietet zusätzlich
shared_array
, die möglicherweise eine geeignete alternative zushared_ptr<std::vector<T> const>
.Nächsten Boost bietet
intrusive_ptr
, die eine leichte Lösung, wenn Sie Ihre Ressource bietet einen Referenzzähler-management bereits und Sie wollen es einführen, um das RAII-Prinzip. Dieses wurde nicht angenommen von der Norm.Einzigartige Eigentum:
Boost hat auch eine
scoped_ptr
, die nicht kopierbar sind und für die Sie können nicht angeben, ein deleter.std::unique_ptr
istboost::scoped_ptr
auf Steroide und sollte Ihre Standard Wahl, wenn Sie benötigen ein smart-pointer. Es ermöglicht Ihnen das angeben einer deleter in seiner Vorlage Argumente und ist beweglichen, im Gegensatz zuboost::scoped_ptr
. Es ist auch voll nutzbar, bei STL-Containern, solange Sie nicht verwenden, operations, müssen kopierbar Typen (offensichtlich).Beachten Sie wieder, dass Boost hat ein array version:
scoped_array
, die die standard unified indem diestd::unique_ptr<T[]>
partielle Spezialisierungendelete[]
den Zeiger stattdelete
ing es (mit derdefault_delete
r).std::unique_ptr<T[]>
bietet auchoperator[]
stattoperator*
undoperator->
.Beachten Sie, dass
std::auto_ptr
ist noch in der Norm, aber es ist veraltet.§D.10 [depr.auto.ptr]
Kein Eigentum:
Verwenden Sie stumm Zeiger (raw-Zeiger) oder Referenzen für non-owning references zu Ressourcen und, wenn Sie wissen, dass die Ressource überleben wird das verweisende Objekt /Bereich. Lieber Verweise und verwenden Sie raw-Pointer, wenn Sie brauchen, entweder die null-Zulässigkeit oder resettability.
Wenn Sie möchten, eine nicht-besitzenden Verweis auf eine Ressource, aber Sie wissen nicht, ob die Ressource überleben wird das Objekt verweist, pack die Ressource in einer
shared_ptr
und verwenden Sie eineweak_ptr
- können Sie testen, ob die übergeordnetenshared_ptr
ist lebendig mitlock
zurückgeben wird, eineshared_ptr
ist nicht-null, wenn die Ressource noch vorhanden ist. Wenn Sie möchten, um zu testen, ob die Ressource ist tot, verwenden Sieexpired
. Die beiden mag ähnlich klingen, aber sind sehr unterschiedlich in das Gesicht der gleichzeitigen Ausführung, wieexpired
garantiert nur Ihr Rückgabewert für diese einzige Anweisung. Eine scheinbar unschuldige test wieist eine mögliche race-condition.
shared_ptr
- und den non-owning pointer auf einweak_ptr
...Ich meinte nicht Referenz auf Zeiger, sondern Referenz statt Zeiger. Wenn es kein Eigentum, es sei denn, Sie müssen resettability (oder die null-Zulässigkeit, aber null-Zulässigkeit ohne reset wäre Recht begrenzt zu sein), können Sie mit einem einfachen Verweis, anstatt einen Zeiger in den ersten Platz.
Ah, ich sehe. 🙂 Ja, die Referenzen sind nicht schlecht, ich persönlich bevorzuge Sie auch in solchen Fällen. Ich werde Sie hinzufügen.
ist eine alternative zu
shared_ptr<T[]>
nichtshared_ptr<vector<T>>
: es kann nicht wachsen.Das ist... genau das, was ich schrieb? Ich sagte, es ist ein Beispiel für eine mögliche race-condition.
InformationsquelleAutor Xeo
Entscheiden, was smart pointer zu verwenden, ist eine Frage der Eigentum. Wenn es darum geht, Ressourcen-management, Objekt-Eine besitzt Objekt B, wenn es in der Kontrolle der Lebensdauer des Objekts B. Zum Beispiel, member-Variablen sind im Besitz Ihrer jeweiligen Objekte, da die Lebensdauer der member-Variablen ist gebunden an die Lebensdauer des Objekts. Sie wählen die smart-Pointer basiert auf, wie das Objekt gehört.
Beachten Sie, dass das Eigentum in ein software-system ist getrennt von Eigentum, wie wir denken würden, dass es außerhalb der software. Zum Beispiel könnte eine person zu "besitzen", Ihre Heimat, aber das bedeutet nicht unbedingt, dass ein
Person
Objekt hat die Kontrolle über die Lebensdauer einesHouse
Objekt. Die Vermischung dieser real-Welt-Konzepte software-Konzepte ist ein sicherer Weg, um das Programm selbst in ein Loch.Wenn Sie das alleinige Eigentum an dem Objekt, verwenden Sie
std::unique_ptr<T>
.Wenn Sie haben gemeinsame Eigentum an dem Objekt...
- Wenn es keine Zyklen in Eigentum, Nutzung
std::shared_ptr<T>
.- Wenn es gibt-Zyklen definieren Sie eine "Richtung" und nutzen
std::shared_ptr<T>
in eine Richtung und diestd::weak_ptr<T>
in der anderen.Wenn das Objekt besitzt Sie, aber es gibt potential, dass Sie keinen Besitzer, verwenden Sie den normalen Zeiger
T*
(z.B. parent-Zeigern).Wenn das Objekt besitzt du (oder sonst garantiert die Existenz), Referenzen verwenden
T&
.Achtung: beachten Sie die Kosten der smart-Pointer. Im Speicher-oder performance-begrenzten Umgebungen, könnte es von Vorteil sein, verwenden Sie einfach normalen Zeiger mit manueller Regelung für die Verwaltung der Speicher.
Kosten:
std::shared_ptr
hat den Aufwand für einen reference count increment auf "kopieren", plus ein Dekrement auf Zerstörung, gefolgt von einem 0-count-check mit Löschung des gehaltenen Objekts. Je nach Implementierung kann dies aufblasen code und Leistungsprobleme verursachen.Beispiele:
Einen binären Baum, der nicht seine eigenen Eltern, aber die Existenz einer Struktur impliziert die Existenz Ihrer Eltern (oder
nullptr
für root), so dass mit einer normalen Zeiger. Ein binärer Baum (mit Wert-Semantik) hat die alleinige Verantwortung für Ihre Kinder, das sind alsostd::unique_ptr
.Hier die Liste der Knoten besitzt seine nächsten und vorherigen Listen, also definieren wir die Richtung und verwenden
shared_ptr
für die nächste undweak_ptr
für prev um den Kreislauf zu durchbrechen.shared_ptr<BinaryTree>
für die Kinder und dieweak_ptr<BinaryTree>
für die Beziehung.Es hängt davon ab, ob der Baum hat eine Wert-Semantik haben oder nicht. Wenn die Menschen gehen, verweist Sie auf Ihren Baum, extern, selbst einmal den Quellcode zerstört wird, dann ja, shared/weak pointer combo am besten wäre.
Wenn sich ein Objekt besitzt Sie und ist garantiert vorhanden ist, warum dann nicht einen Verweis.
Wenn Sie Referenz benutzen, man kann nicht immer ändern, die Eltern, die möglicherweise oder möglicherweise nicht hindern, das design. Für den Ausgleich der Bäume, das behindern würde.
+1, aber sollten Sie hinzufügen eine definition von "Eigentum" in der ersten Zeile. Ich finde mich oft, dass ganz klar sagen, es geht um Leben & Tod des Objekts, nicht das Eigentum in einer domain-spezifische Bedeutung.
InformationsquelleAutor Peter Alexander
Verwenden
unique_ptr<T>
die ganze Zeit, außer wenn Sie Sie brauchen, die Verweiszählung, in welchem Fall verwendenshared_ptr<T>
(und für den sehr seltenen Fällen,weak_ptr<T>
zu verhindern, die Referenz-Zyklen). In fast jedem Fall übertragbar einzigartige Eigentum ist in Ordnung.Raw-Pointer: nur Gut, wenn Sie brauchen, kovariante gibt, die nicht-besitzenden zeigen, die passieren können. Sie sind nicht enorm hilfreich, sonst.
Array-Zeiger:
unique_ptr
hat eine Spezialisierung fürT[]
die automatisch Anrufedelete[]
auf das Ergebnis, so können Sie sicher tununique_ptr<int[]> p(new int[42]);
zum Beispiel.shared_ptr
Sie müssen noch einen custom deleter, aber Sie würden Sie nicht brauchen eine spezielle shared oder unique-array-Zeiger. Natürlich, solche Dinge sind in der Regel am besten ersetzt durchstd::vector
sowieso. Leidershared_ptr
keine array-access-Funktion, also würden Sie immer noch manuell aufrufenget()
, aberunique_ptr<T[]>
bietetoperator[]
stattoperator*
undoperator->
. In jedem Fall müssen Sie Grenzen selbst überprüfen. Dies machtshared_ptr
etwas weniger user-freundlich, obwohl wohl die generischen Vorteil und kein Boost Abhängigkeit machtunique_ptr
undshared_ptr
den Gewinnern wieder.Scoped-Pointer: Made irrelevant
unique_ptr
, wieauto_ptr
.Es gibt wirklich nichts mehr. In C++03 ohne move-Semantik diese situation war sehr kompliziert, aber in C++11 die Beratung ist sehr einfach.
Gibt es immer noch verwendet, für die anderen smart-Pointer, wie
intrusive_ptr
oderinterprocess_ptr
. Allerdings sind Sie sehr Nische und völlig unnötig in den Allgemeinen Fall.Ich schon bearbeitet für solche.
Hmm, so wie ich Lesen, dass es Situationen gibt, welche beide kovariante Rückgabe und nicht-besitzenden. Ein umschreiben könnte gut sein, wenn Sie bedeutete die union eher als Kreuzung. Ich würde auch sagen, dass die iteration lohnt sich, Besondere Erwähnung auch.
std::unique_ptr<T[]>
bietetoperator[]
stattoperator*
undoperator->
. Es ist wahr, dass Sie noch tun müssen, gebunden überprüfung selbst wenn.InformationsquelleAutor Puppy
Fällen, Wann
unique_ptr
:Fällen, Wann
shared_ptr
:Fällen, Wann
weak_ptr
:Fühlen Sie sich frei zu Bearbeiten, und fügen Sie mehr
InformationsquelleAutor Lalaland