Die Antwort sollte aus der Standardspezifikation der Bewegungszuweisung in [unique.ptr.single.assign] / 2:
ersichtlich seinEffekte: Übernimmt die Eigentumsrechte von
u
auf*this
, als ob durch Aufruf vonreset(u.release())
gefolgt von einer Zuweisung vonstd::forward<D>(u.get_deleter())
.
Die Zuordnung der Verschiebung ist nicht identisch mit reset(u.release())
, weil sie etwas Zusätzliches tut.
Der zusätzliche Effekt ist wichtig, ohne ihn können Sie mit benutzerdefinierten Deletern undefiniertes Verhalten erhalten:
%Vor%Die zweite Version ist vielleicht nicht ausnahmslos sicher, denke ich. Es entspricht:
%Vor% Wenn also der Aufruf von std::unique_ptr::reset
ausgelöst wird (was der Fall sein kann, wenn das Löschen des verwalteten Objekts ausgelöst wird), dann haben Sie ein unreferiertes Objekt, das niemals zerstört wird. Im Falle der Verschiebungszuweisung kann (und sollte) std::unique_ptr
mit der tatsächlichen Bewegung warten, bis das ursprüngliche Objekt p1
ordnungsgemäß zerstört wurde.
Beachten Sie jedoch, dass dies nur dann ein Problem darstellt, wenn der Destruktor des verwalteten Objekts einen Fehler verursachen könnte, der in fast allen Fällen falsch ist, oder wenn Sie einen benutzerdefinierten Deleter verwenden, der einen Fehler verursacht. In der Praxis gibt es normalerweise keinen Verhaltensunterschied zwischen den beiden Codefragmenten.
BEARBEITEN: Am Ende Jonathan weist in seinem Kommentar darauf hin, dass der benutzerdefinierte Deleter vom Standard nicht geworfen werden muss, was in der Tat das Werfen von% co_de verursacht % ziemlich unwahrscheinlich / nicht konform. Aber er weist auch darauf hin, dass es einen weiteren Unterschied gibt, dass nur eine Bewegungszuweisung auch benutzerdefinierte Deletes verschiebt, für die er auch eine Antwort geschrieben hat.
Aber abgesehen vom tatsächlichen resultierenden Verhalten gibt es einen großen konzeptionellen Unterschied zwischen den beiden. Wenn eine Zuweisungszuweisung angebracht ist, dann führe eine Zuweisungszuweisung durch und versuche, sie nicht durch einen anderen Code zu emulieren. In der Tat kann ich keinen Grund darstellen, den ersten Codeausschnitt eins zu eins durch den zweiten zu ersetzen. DeadMG liegt darin, dass std::unique_ptr::reset
nur verwendet werden sollte, wenn Sie wirklich wissen, was Sie tun und in welchem Kontext Sie mit nicht verwalteten dynamischen Objekten herumhantieren.
Tags und Links c++ c++11 unique-ptr