Alternativen static_pointer_cast für unique_ptr
Ich verstehen, dass die Verwendung static_pointer_cast
mit unique_ptr
würde dazu führen, dass eine gemeinsame Verantwortung, die darin enthaltenen Daten.
In anderen Worten, was ich tun möchte ist:
unique_ptr<Base> foo = fooFactory();
//do something for a while
unique_ptr<Derived> bar = static_unique_pointer_cast<Derived>(foo);
Sowieso tun, dass die Ergebnisse mit zwei unique_ptr
sollten nie zur gleichen Zeit existieren, so ist es einfach verboten.
Recht, es macht Sinn, absolut, das ist, warum es existiert nicht so etwas wie static_unique_pointer_cast
in der Tat.
So weit, in Fällen, in denen ich speichern möchte Zeigern auf die Basisklasse, aber ich brauche, um Sie zu werfen, um einige abgeleitete Klassen (als ein Beispiel vorstellen, ein Szenario mit type erasure), die ich benutzt habe shared_ptr
s denn, was habe ich oben erwähnt.
Jedenfalls war ich zu erraten, ob es alternativen zu shared_ptr
s für so ein problem ist oder ob das wirklich die beste Lösung in diesem Fall.
static_pointer_cast
ist nur definiert für das argument type std::shared_ptr<T>
- es ist nicht verwendbar bei allen mit unique_ptr
Ja, ich weiß, ich schrieb fast das gleiche in der Frage zu sagen, das nicht existiert, eine Entsprechung für die
unique_ptr
.Warum type-erasure führen zu downcasting? Wenn Sie brauchen, um werfen Sie Ihre base-Klasse in einen abgeleiteten Typ ist, ist es am häufigsten, mit Ausnahme von sehr wenigen Fällen, eine design-Frage, die gelöst werden sollten, unterschiedlich.
Stellen Sie sich
struct B { virtual void f() = 0; }; template<class T> struct D: public B { void f() override { /* do something with D */ } };
haben Sie jemals etwas getan? Mit der guten Mischung aus Wrapper und static_pointer_cast
Sie können eine Menge interessante Dinge.Naja, ich würd sagen, dass die anderen Antworten haben einen direkten und sauberen Ansatz, aber... es funktioniert... das ist es. 🙂
InformationsquelleAutor skypjack | 2016-03-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Raw-Pointer
Die Lösung für Ihr problem ist die roh - (nicht-Besitz) Zeiger und warf es - dann lass einfach die raw-Zeiger außerhalb des Bereichs und lassen Sie die restlichen
unique_ptr<Base>
constrol die Lebensdauer der im Eigentum Objekt.Wie diese:
Unique_pointer_cast
Die andere Möglichkeit ist die Verwendung der
release()
Funktionunique_ptr
wickeln Sie es in einem anderen unique_ptr.Wie diese
Denken Sie daran, dass diese ungültig macht, die alten Zeiger
foo
Referenz von raw-Pointern
Nur der Vollständigkeit halber die Antwort, diese Lösung war tatsächlich vorgeschlagen, als eine Modifikation des raw-Zeiger von der OP in die Kommentare.
Ähnlich wie mit raw-Pointern kann man cast dem raw-Pointer und dann erstellen Sie einen Verweis durch derefering. In diesem Fall ist es wichtig, zu garantieren, dass die Lebensdauer der erstellten Referenz nicht übersteigt die Lebensdauer der unique_ptr.
Beispiel:
FROM
abgeleitet werden, wie instd::static_pointer_cast
?Ja, natürlich will ich nicht zu viel mit raw-Pointern, aber du hast mir einen guten Hinweis darauf, wie auch immer... Die Umsetzung von
static_unique_pointer_cast
ist interessant, aber leider nicht gut mit der Idee, ausgedrückt in der Frage) speichern Zeiger, denn sobald Sie ungültig geworden sind, müssen Sie neu initialisiert werden für Zukunft verwendet nach der aktuellen Nutzung, so dass es würde dazu führen, dass eine riesige Menge an Arbeit, um einen container.guter Punkt, @aschepler, fügte ich hinzu.
die Frage, die sich stellt, ist: wer ist der Eigentümer des Objekts hingewiesen (nämlich die verantwortlich für die Löschung)? Nur einen einzigen Zeiger auf ein mal? -> Verwenden Sie ein unique_ptr, von denen es vielleicht nur einen einzigen, in einer Zeit,. Mehrere (ggf. verschiedene Klassen)? -> shared-Pointer. Für Hinweise, die sind nicht verantwortlich für die Löschung, die Verwendung von raw-Pointer. Und wenn Sie sich entscheiden, einen einzigen Eigentümer, Sie sind wahrscheinlich der einzige Weg, um die Zeiger der anderen Klassen auf das gleiche Objekt, während das Eigentum beim ursprünglichen Objekt.
Naja, nicht so einfach, es ist eine Sammlung von Zeigern zu geben-gelöscht-Klassen, die sind gegossen nach vorn, sobald benötigt, damit der Besitzer ist, aber immer noch ich können entstehen Probleme, als wären Sie zwei. Trotzdem, es ist eine Frage der raw-pointer mit
get
-, Guss-und derefer es, um wieder eine Referenz für die einen kann Garantie für die Lebensdauer. Ansonsten kann ich auch mal mitshared_ptr
s natürlich... 🙂InformationsquelleAutor Anedar
Nur, wenn Sie es definieren schlecht. Die offensichtliche Lösung wäre es zur übertragung des Eigentums, so dass das source-Objekt beendet leer.
Wenn Sie nicht möchten, dass zur übertragung des Eigentums dann nur mit einem raw-pointer.
Oder wenn Sie wollen, zwei Besitzer dann verwenden
shared_ptr
.Wie es scheint, deine Frage ist nur zum Teil über die tatsächliche cast-operation, und teilweise nur Mangel an einer klaren eigentumsrechtlichen Politik für die Zeiger. Wenn Sie mehrere Besitzer, ob Sie beide den gleichen Typ verwenden, oder ob man einen cast auf einen anderen Typ, dann sollten Sie nicht verwenden
unique_ptr
.Nein, das ist nicht der Grund, warum es nicht vorhanden ist. Es existiert nicht, weil es trivial, um es selbst schreiben, wenn Sie es brauchen (und solange Sie geben es vernünftige Semantik von unique ownership). Nur die Zeiger mit
release()
wirken, und legen Sie es in einem anderenunique_ptr
. Einfach und sicher.Das ist nicht der Fall für die
shared_ptr
, wo die "offensichtliche" Lösung nicht das richtige tun:Schaffen würde, die zwei verschiedene
shared_ptr
Objekte, die den gleichen Zeiger, aber nicht das Eigentum zu teilen (d.h., Sie würden beide versuchen, es zu löschen, verursacht Undefiniertes Verhalten).Wenn
shared_ptr
wurde ersten standardisierten gab es keinen sicheren Weg, das zu tun, sostatic_pointer_cast
und den zugehörigen casting-Funktionen definiert wurden. Sie benötigt den Zugriff auf die details der Implementierung desshared_ptr
Buchhaltung info an die Arbeit.Jedoch, während die C++11-Standardisierung
shared_ptr
wurde verstärkt durch die Zugabe von "aliasing-Konstruktor" der es erlaubt, die Besetzung einfach und sicher:Wenn dieses feature war schon immer Teil der
shared_ptr
dann ist es möglicherweise, vielleicht sogar wahrscheinlich, dassstatic_pointer_cast
würde nie definiert wurden.Ich bin damit einverstanden, ehrlich gesagt, ich denke, ich bin vor ein XY-problem, aber die Frage war für mich interessant zu wissen, was andere getan haben würde, wenn Sie mich.
std::exchange
ist einfach zu schreiben und niemand nutzt es. Wie hast es bekommen? 🙂eine gute Frage 🙂
Ich denke
std::exchange
eignet sich hervorragend als Ente.InformationsquelleAutor Jonathan Wakely
Ich möchte etwas ergänzen zu der vorherigen Antwort von Anedar die Anrufe, die
release()
member-Methode der angegebenenstd::unique_ptr< U >
. Will man zur Umsetzung einerdynamic_pointer_cast
als auch (zusätzlich zu einemstatic_pointer_cast
) für die Konvertierungstd::unique_ptr< U >
zustd::unique_ptr< T >
, müssen sicherstellen, dass die Ressource bewacht von der unique pointer ist korrekt freigegeben, im Fall derdynamic_cast
ausfällt (d.h. es gibt einenullptr
). Andernfalls tritt ein Speicherverlust auf.Code:
Ausgang (mögliche Reihenfolge):
Die Destruktoren von
C
undD
wird nicht aufgerufen werden, wenn man setzt:InformationsquelleAutor Matthias