web-dev-qa-db-ger.com

Unterschiede zwischen std :: make_unique und std :: unique_ptr mit new

Hat std::make_unique irgendwelche Effizienzvorteile wie std::make_shared?

Im Vergleich zum manuellen Konstruieren von std::unique_ptr:

std::make_unique<int>(1);         // vs
std::unique_ptr<int>(new int(1));
111
NFRCR

Die Motivation hinter make_unique ist in erster Linie zweierlei:

  • make_unique ist sicher zum Erstellen von temporären Dateien, wohingegen Sie bei expliziter Verwendung von new die Regel beachten müssen, nicht unbenannte temporäre Dateien zu verwenden.

    foo(make_unique<T>(), make_unique<U>()); // exception safe
    
    foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
    
  • Die Hinzufügung von make_unique bedeutet schließlich, dass wir den Leuten sagen können, dass sie new niemals verwenden sollen und nicht die vorherige Regel, dass sie new niemals verwenden sollen, außer wenn Sie einen unique_ptr erstellen.

Es gibt auch einen dritten Grund:

  • make_unique erfordert keine redundante Typverwendung. unique_ptr<T>(new T()) -> make_unique<T>()

Keiner der Gründe besteht darin, die Laufzeiteffizienz zu verbessern, wie dies bei Verwendung von make_shared der Fall ist (aufgrund der Vermeidung einer zweiten Zuweisung auf Kosten einer potenziell höheren Spitzenbelegung des Speichers).

* Es wird erwartet, dass C++ 17 eine Regeländerung enthält, die bedeutet, dass dies nicht länger unsicher ist. Siehe C++ Ausschusspapiere P0400R und P0145R .

129
bames53

std::make_unique und std::make_shared gibt es aus zwei Gründen:

  1. Damit Sie die Vorlagentypargumente nicht explizit auflisten müssen.
  2. Zusätzliche Ausnahmesicherheit bei der Verwendung von std::unique_ptr oder std::shared_ptr Konstruktoren. (Siehe den Abschnitt Anmerkungen hier .)

Es geht nicht wirklich um Laufzeiteffizienz. Es gibt das gewisse Etwas, dass der Steuerblock und das T auf einmal zugewiesen werden, aber ich denke, das ist eher ein Bonus als eine Motivation für das Vorhandensein dieser Funktionen.

11
Timothy Shields

Ein Grund, warum Sie std::unique_ptr(new A()) oder std::shared_ptr(new A()) direkt anstelle von std::make_*() verwenden müssten, besteht darin, dass Sie nicht auf den Konstruktor der Klasse A außerhalb von zugreifen können aktueller Geltungsbereich.

6