ist es besser, zu verwenden shared_ptr.reset-oder-operator =?
Ich versuche, wickeln Sie meinen Kopf herum, die neue Redewendungen für C++11.
Scheint es, dass mit shared_ptr zumindest, es gibt einen inhaltlichen Unterschied zwischen der Verwendung new T()
und make_shared<T>()
.
Aber was ist das zurücksetzen eines shared-pointer zu Punkt, um eine neue Instanz von etwas. Früher hätte ich in der Regel verwenden reset(new T())
Mitglied. Jedoch steht dies nicht unter dem gleichen problem leiden nicht mit make_shared() in Erster Linie? (d.h. es erlaubt nicht make_shared zu reservieren das Objekt, deshalb ist es gezwungen, legen Sie die ref-Anzahl in einer separaten Zuweisung statt, die in der gleichen Verteilung wie die T selbst?)
Ist es einfach besser für die Zukunft, um zu verwenden:
mysharedptr = make_shared<T>(args...);
Oder gibt es eine bessere Möglichkeit?
Werden und sollte nicht zurückgesetzt bieten variadic Weiterleitung der Argumente als make_shared, so dass man schreiben konnte mysharedptr.reset(args...);?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist in der Tat ein wesentlicher Unterschied zwischen:
Und:
Die erste version führt eine Zuweisung für das
T
Objekt, dann führt eine separate Zuordnung zu erstellen der Referenz-Zähler. Die zweite version führt eine einzige Mittelzuweisung für das Objekt und der Referenz-Zähler, indem Sie in einem zusammenhängenden Bereich des Speichers, was zu weniger Speicher-overhead.Auch einige Implementierungen in der Lage sind, weitere Raum-Optimierungen im Falle der
make_shared<>
(siehe "Wir Wissen Wo Du wohnst" Optimierung erfolgt durch die Mitgliedstaaten-Umsetzung).Dies ist jedoch nicht der einzige Grund, warum
make_shared<>
vorhanden ist. Die version basiert auf explizitennew T()
ist nicht exception-sicher in einigen Situationen, insbesondere beim aufrufen einer Funktion akzeptiert eineshared_ptr
.Hier, der compiler könnte wertet die erste
new T()
Ausdruck, bewerten Sie dann die zweitenew T()
Ausdruck, dann konstruieren Sie die entsprechendenshared_ptr<>
Objekte. Aber was ist, wenn die zweite Zuweisung bewirkt, dass eine Ausnahme vor der ersten zugewiesenen Objekt ist gebunden an seineshared_ptr<>
? Es wird durchgesickert sein. Mitmake_shared<>()
ist dies nicht möglich:Weil die zugewiesenen Objekte sind an die jeweiligen
shared_ptr<>
Objekte, die sich in jeder Funktion aufrufen, ummake_shared<>()
dieser Aufruf ist exception-sicher. Dies ist ein weiterer Grund, warum nacktnew
sollte niemals verwendet werden, es sei denn, Sie wirklich wissen, was Sie tun. (*)Unter Berücksichtigung Ihrer Bemerkung über
reset()
Sie zu Recht in der Beobachtung, dassreset(new T())
führen separate Zuweisungen für den counter und das Objekt, genauso wie die Errichtung eines neuenshared_ptr<>
führt eine separate Zuweisung, wenn ein raw-pointer als argument übergeben. Daher ist eine Zuordnung übermake_shared<>
vorzuziehen ist (oder auch eine Aussage wiereset(make_shared<T>())
).Ob oder nicht
reset()
unterstützen sollte, die eine Variable Argumentliste, das ist wohl eher eine Art der offenen Diskussion, für die StackOverflow ist nicht eine gute Passform.(*) Es gibt ein paar Situationen, die verlangen noch es. Zum Beispiel die Tatsache, dass der C++ - Standard-Bibliothek fehlt eine entsprechende
make_unique<>
Funktion fürunique_ptr
, so müssen Sie selbst einen schreiben. Eine andere situation ist, wenn Sie nicht möchten, dass das Objekt und dem Zähler zugeordnet werden, auf einem einzigen Speicher-block, weil das Vorhandensein von weak-Pointer auf das Objekt wird verhindert, dass die gesamte block wird freigegeben, auch wenn keine mehr zu besitzen Verweise auf das Objekt existieren.new
bei allen, abermake_unique
auf ein minimum reduzieren. Dies verhindert mögliche Leckagen design für eine Zuweisung.make_unique
ist die Ausnahme, ich hatte im Hinterkopf, für die die Verwendungnew
. Btw, kennt Ihr zufällig warum es keinemake_unique
in der standard-Bibliothek?make_shared
wenn Sie memory-gedrückt, da die Optimierung wird halten, der Speicher-block, der sich am Leben, bis es nicht mehr weak-Pointer.reset
mehr gearbeitet wie ein containeremplace
- Funktion, könnte es die Wiederverwendung von Speicher, aber diese Annahme nicht zu halten, und eine ziemlich große design-änderung. Die C++11 smart Pointer sind nur verantwortlich für die ein Objekt in Besitz, nicht seine Erschaffung oder allokierung von Speicher für Sie. Anstatt zu zerstören, freigeben, zuweisen und erstellen, vielleicht wollen Sie nur zu tun*up = T(args...)
statt?shared_ptr<T>::emplace<Args...>(Args&&... args)
eher als überladenreset
.make_shared<>()
ist nicht möglich, wenn z.B. der Konstruktor und/oder Destruktor private (d.h. Sie erzeugt eine form von singleton-oder zumindest vollständig kontrolliert allocation/deallocation der class-Objekte.)Richtig,
reset(new T...)
leidet, alle Fragen dershared_ptr(new T...)
; es wird Ergebnis in doppelte Zuweisung und auch ist nicht exception-sicher (es gibt nicht viel chance auf ein Leck, es sei dennbad_alloc
geschieht innerhalbreset
).reset
dokumentiert ist, als äquivalent zushared_ptr<T>(ptr).swap(*this)
, so könnte man auch schreiben:Zuweisung von
make_shared<T>
ist fast gleichwertig, der einzige Unterschied ist, dass die relative Reihenfolge der Löschung der altenT
und die Zerstörung des temporärenshared_ptr
, die nicht beobachtbar.myptr = std::move(make_unique<T>(...))
move
ist nicht erforderlich; der Rückgabewert vonmake_shared
odermake_unique
ist ein prvalue, so bindet eine rvalue-Referenz.p = make_unique<derived>()