2013-10-07 5 views
7

Aus der Forschung, die ich getan habe, klingt es wie std::make_shared ist die bevorzugte Möglichkeit, eine std::shared_ptr zu konstruieren. Speziell weil:Gibt es eine Situation, in der ich nicht std :: make_shared verwenden würde?

  1. Es führt nur eine Speicherzuweisung, im Vergleich zu new, die mindestens zwei durchführt.
  2. Wenn der ctor an make_shared Würfe übergeben, dann wird es nicht lecken, wie es mit neuen wird.

Meine Frage ist, unter der Annahme, dass ich ein shared_ptr will, sollte ich immer Verwendung make_shared, oder gibt es Fälle, in denen new bevorzugt?

+0

'shared_ptr (neues int)' wird Speicher nicht verlieren, wenn der 'shared_ptr' Konstruktor wirft; Das scheint mir dein zweiter Punkt zu bedeuten. – Simple

Antwort

6

Da der Zähler und das Objekt dieselbe Zuweisung haben, teilen sie sich auch die gleiche Freigabe.

Der Zähler muss bestehen bleiben, bis die letzten shared_ptr und weak_ptr weggehen. Wenn Sie ein großes Objekt (oder viele kleine Objekte) mit langlebigen weak_ptr s haben, kann dies zu Speicherkonflikten führen, wenn Sie die shared_ptr s über make_shared zuweisen.

Zweitens, wenn Sie eine API eines Drittanbieters haben, die Ihnen einen Zeiger oder ein Ressourcenhandle übergibt und möglicherweise über eine eigene Dispose-Funktionalität verfügt, ist make_shared weder geeignet noch in jedem Fall möglich. Erstellen Sie Ihre eigenen make_ Funktionen können die unordentlichen Details aus dem Weg halten Sie mit diesem Problem umgehen, und befasst sich auch mit der Ausnahme Ecke Fall.

Schließlich, während gemeinsame Zeiger sind genial, sie sind auch übermäßig stark. Ziemlich oft möchte ich einen unique_ptr oder sogar einen boost::scoped_ptr oder einen intrusiven Referenzzählzeiger oder dergleichen, um den Besitz darzustellen. shared_ptr sollte nur verwendet werden, wenn die Situation tatsächlich beinhaltet shared Eigentum der Ressource: mit ihm willy nilly, weil es "einfach" ist neigt dazu, mit der Ressource Äquivalent von Spaghetti-Code enden.

+4

Bonuspunkte für den letzten Absatz. Während das in der Frage nicht direkt angesprochen wurde, kann es in diesem Zusammenhang nicht oft genug gesagt werden. –

2

Möglicherweise müssen Sie mit Legacy-Code arbeiten, der ein dynamisch zugewiesenes Objekt zurückgibt. In diesem Fall müssten Sie den std::shared_ptr<T> ctor mit dem Zeigerparameter verwenden. Es ist nicht vorzuziehen, std::make_shared zu verwenden, aber es ermöglicht Ihnen, alle std::shared_ptr<T> Güte mit Legacy-Code zu verwenden.

Ich weiß, dass dies nicht unbedingt gleichwertig ist, den std::shared_ptr<T> Ctor mit new direkt zu verwenden, aber es ist ein gültiger Anwendungsfall von std::shared_ptr<T> wo make_shared nicht genutzt werden kann.

0

Ich lief Probleme mit make_shared für eine Klasse mit einem privaten Konstruktor (von einer statischen Factory-Methode). Ich denke nicht, dass es eine einfache Lösung dafür gibt.

+0

Ich denke, es gibt einen Defekt, der darüber angesprochen wurde; Sollten Sie in der Lage sein, 'make_shared' zu einem Freund zu machen? Der Standard ist unklar, ob es funktioniert oder nicht. – Simple

+0

Ich habe eine Problemumgehung, die Sie 'make_shared' mit einem" privaten "Konstruktor verwenden können: http://ideone.com/O93w6o – Simple

1

Ich bin ein wenig unsicher über die Interpretation Ihrer Frage. Ich gehe davon aus, dass es gerechtfertigt ist, einen shared_ptr<T> zu verwenden; Ich kann nur an zweiter Stelle Yakk auf den Gründen, warum Sie nicht shared_ptr in erster Linie verwenden möchten.

Es ist eine Situation, wo man nicht make_shared oder allocate_shared verwenden kann, die shared_ptr zu konstruieren, aber Sie müssen den entsprechenden Ctor verwenden: Wenn Sie in einem benutzerdefinierten deleter übergeben müssen, siehe (3) und (4) bei the ctors of shared_ptr.

0

sollte ich immer make_shared verwendet wird, oder gibt es Fälle, in denen neue

make_shared erlaubt ist nicht bevorzugt ist, wenn wir sonst einen nackten Zeiger in shared_ptr zugewiesen von jemandem zu speichern. und es kann nur public Konstruktoren aufrufen. In einigen Compilern gibt es jedoch Berichte über den Zugriff auf geschützte Konstruktoren mit make_shared like this.