shared_ptr als Parameter
-
Und dann ist B eindeutig besser.
-
perreff schrieb:
Hmm, ich habe einen Fehler gemacht. Der Beispielcode gilt auch für Konstruktor B.
Haha, das wollte ich auch gerade erwähnen, da war doch was mit const. Ja, B ist besser. Und ich denke immer noch, dass der TE einen unique_ptr will.

-
Was ist der Unterschied zwischen shared und unique pointer?
-
paraUhu schrieb:
Was ist der Unterschied zwischen shared und unique pointer?
Aha!

Der shared_ptr teilt (wie der Name schon sagt) den Besitz an dem Objekt auf das er zeigt. Ein unique_ptr ist immer alleiniger Besitzer seines Objekts.
Mal an einem Beispiel deutlich:// Bei main anfangen zu lesen und dem Programmlauf folgen void foo(std::shared_ptr<MyClass> my_class) { // Jetzt wurde der Pointer kopiert, es gibt zwei shared_ptr die auf das gleiche Objekt zeigen. shared_ptr zählt weiter mit. my_class->someFancyFunction(); } // Wieder nur ein shared_ptr int main() { std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>("Parameter"); // Hier gibt es nur eine Referenz auf das Objekt, shared_ptr zählt mit. foo(my_class); } // Keine Referenz mehr, Objekt wird zerstört.Das Ganze kann schon nett sein, aber man braucht es halt eher selten. Wenn man einfach nur kein delete möchte, nutzt man unique_ptr.
int main() { std::unique_ptr<MyClass> ptr(new MyClass("Parameter")); // make_unique gibt es leider nicht. Aber make_shared ruft auch nur new auf. // Irgendwas machen } // Objekt wird automatisch gelöschtEin unique_ptr kann aber nicht kopiert werden (logischerweise), du kannst ihn nur mit std::move übergeben.
-
Achso. Ich kannte den unter dem Namen auto_ptr.
Nene, shared_ptr ist schon der richtige smart pointer für mich:)
-
cooky451 schrieb:
Aber make_shared ruft auch nur new auf.
Nein! Bei make_shared liegen sowhl das Objekt, als auch der shared und der weak-count am Stück im Speicher! Bei make_unique gäbe es so einen Vorteil nicht, daher wollten sie das nicht in den Standard aufnehmen. make_unique könnte man aber einfach selbst implementieren, z.B. so:
template <typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); }
-
paraUhu schrieb:
Macht man das dann am besten by value (Im Code wie bei A) oder per Reference (wie bei B)?
Wenn Du den shared_ptr nicht sowieso kopieren musst, würde ich es per ref-to-const (also wie in
an die Funktion übergeben; denn dann spart man sich die Modifikation des Referenzzählers und da diese threadsicher passieren muss, kostet das natürlich. Aber in Deinem Beispiel willst Du ja eine Kopie im Objekt speichern. Dann könnte man auch folgendes schreiben:class Foo { shared_ptr<Bar> barptr_; public: Foo(shared_ptr<Bar> bar) : barptr_([b]std::move([/b]bar[b])[/b]) {} };Das würde ich in diesem Fall sogar vorziehen. Das Kopieren überlässt man hier dem Compiler, der das eventuell wegoptimieren kann. Die Move-Konstruktion eines shared_ptr ist sehr effizient, erfordert also keine Modifikationen des Referenzzählers.
Und ja,
make_sharedhat nicht nur den Vorteil, dassauto sp = make_shared<MyClassType>(3.14159265);kürzer ist als
shared_ptr<MyClassType> sp ( new MyClassType(3.14159265) );sondern auch den, dass
make_shareddie Gelegenheit hat, das Objekt und die Kontrollstruktur (Referenzzähler, Deleter, etc) in einem Block auf einen Schlag zu allozieren.Obwohl ein unique_ptr keine solche dynamisch zu allozierende Kontrollstruktor benötigt, ist IMHO make_unique trotzdem sinnvoll, da man damit erreichen kann, dass das unque_ptr Objekt sofort mit einem Zeiger initialisiert wird (Sequenzpunkte des Funktionsaufrufs); denn so etwas
some_funktion( unique_ptr<Foo>(new Foo(123)), unique_ptr<Bar>(new Bar(321)) );ist nicht Ausnahme-sicher. Die Reihenfolge der Auswertung ist nicht festgelegt und so kann es passieren, dass das zweite Objekt erzeugt wird bevor das erste dem unique_ptr übergeben wurde. Man hätte im Falle einer Ausnahme ein Speicherleck. Ohne make_unique müssten wir vorher die Zeiger einzeln anlegen:
unique_ptr<Foo> pfoo (new Foo(123)); unique_ptr<Bar> pbar (new Bar(321)); some_funktion( std::move(pfoo), st::move(pbar) );Cheers!
k.k.
-
Genau zu dem Thema Ausnahmesicherheit, das krümelkacker angesprochen hat, gibts übrigens einen neuen GOTW-Blogeintrag:
http://herbsutter.com/2011/12/02/gotw-102-exception-safe-function-calls-difficulty-710/
-
Aha. So ein Zufall!
Das hatte ich noch nicht gesehen.
-
Haha, der Paprikachu mit seinem lieblings make_unique ist einfach überall.

-
:p