Hat std::make_unique
irgendwelche Effizienzvorteile wie std::make_shared
?
Im Vergleich zum manuellen Erstellen std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
c++
c++11
c++14
smart-pointers
unique-ptr
NFRCR
quelle
quelle
make_shared
es eine Effizienz, nur den langen Handcode zu schreiben?make_shared
sowohl der Speicherplatz für das Objekt als auch der Speicherplatz für den Steuerblock in einer einzigen Zuordnung zugeordnet werden können. Die Kosten hierfür sind, dass das Objekt nicht getrennt vom Steuerblock freigegeben werden kann. Wenn Sie alsoweak_ptr
viel verwenden, wird möglicherweise mehr Speicher benötigt.Antworten:
Die Motivation dahinter
make_unique
ist in erster Linie zweierlei:make_unique
ist sicher für das Erstellen von Provisorien, während Sie bei expliziter Verwendungnew
die Regel beachten müssen, unbenannte Provisorien nicht zu verwenden.Das Hinzufügen von
make_unique
finally bedeutet, dass wir den Leuten sagen können, dass sie "niemals"new
anstelle der vorherigen Regel "niemals" verwenden sollen,new
außer wenn Sie einunique_ptr
" machen ".Es gibt auch einen dritten Grund:
make_unique
erfordert keine redundante Typverwendung.unique_ptr<T>(new T())
->make_unique<T>()
Keiner der Gründe beinhaltet die Verbesserung der Laufzeiteffizienz wie bei der Verwendung
make_shared
(aufgrund der Vermeidung einer zweiten Zuweisung auf Kosten einer möglicherweise höheren Spitzenspeicherauslastung).* Es wird erwartet, dass C ++ 17 eine Regeländerung enthält, die bedeutet, dass dies nicht länger unsicher ist. Siehe C ++ - Ausschussdokumente P0400R0 und P0145R3 .
quelle
std::unique_ptr
undstd::shared_ptr
deshalb können wir den Leuten sagen, sie sollen "niemals benutzennew
".make_shared
und somake_unique
ist das letzte Stück, das vorher fehlte.f
:f(unique_ptr<T>(new T), function_that_can_throw());
- die Antwort zu zitieren: Die Compiler Aufruf erlaubt ist (in dieser Reihenfolge):new T
,function_that_can_throw()
,unique_ptr<T>(...)
. Offensichtlich, wennfunction_that_can_throw
tatsächlich wirft, dann lecken Sie.make_unique
verhindert diesen Fall. Also ist meine Frage beantwortet.std::make_unique
undstd::make_shared
gibt es aus zwei Gründen:std::unique_ptr
oderstd::shared_ptr
Konstruktoren. (Siehe den Abschnitt Notizen hier .)Es geht nicht wirklich um Laufzeiteffizienz. Es gibt ein bisschen über den Steuerblock und die
T
Zuweisung auf einmal, aber ich denke, das ist mehr ein Bonus und weniger eine Motivation für das Vorhandensein dieser Funktionen.quelle
std::make_shared
sicher, dass mindestens einer von ihnen in den Smart Pointer eingeschlossen wird, bevor die andere Speicherzuweisung erfolgt, sodass keine Lecks auftreten.Ein Grund, warum Sie
std::unique_ptr(new A())
oderstd::shared_ptr(new A())
direkt verwenden müssten,std::make_*()
ist, dass Sie nicht auf den Konstruktor der KlasseA
außerhalb des aktuellen Bereichs zugreifen können .quelle
Funktionsaufruf berücksichtigen
Angenommen, new ist
A()
erfolgreich, newB()
löst jedoch eine Ausnahme aus: Sie fangen sie ab, um die normale Ausführung Ihres Programms fortzusetzen. Leider verlangt der C ++ - Standard nicht, dass Objekt A zerstört und sein Speicher freigegeben wird: Der Speicher leckt stillschweigend und es gibt keine Möglichkeit, ihn zu bereinigen. Wenn Sie A und B einwickeln, könnenstd::make_uniques
Sie sicher sein, dass das Leck nicht auftritt:Der Punkt hier ist, dass
std::make_unique<A>
undstd::make_unique<B>
sind jetzt temporäre Objekte, und die Bereinigung von temporären Objekten ist im C ++ - Standard korrekt angegeben: Ihre Destruktoren werden ausgelöst und der Speicher freigegeben. Wenn Sie können, ziehen Sie es immer vor, Objekte mitstd::make_unique
und zuzuweisenstd::make_shared
.quelle