Was sind die Unterschiede zwischen std :: move und unique_ptr :: reset?

8

Für std::unique_ptr s p1 und p2 , was sind Unterschiede zwischen std::move() und std::unique_ptr::reset() ?

%Vor%     
hhbilly 13.12.2012, 12:50
quelle

3 Antworten

15

Die Antwort sollte aus der Standardspezifikation der Bewegungszuweisung in [unique.ptr.single.assign] / 2:

ersichtlich sein
  

Effekte: Übernimmt die Eigentumsrechte von u auf *this , als ob durch Aufruf von reset(u.release()) gefolgt von einer Zuweisung von std::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%     
Jonathan Wakely 13.12.2012, 13:25
quelle
5

Der erste kann Sie warnen, wenn z. B. ein Destruktor nicht übereinstimmt. Außerdem ist release() eine sehr gefährliche Funktion, und Ihr triviales Beispiel ist korrekt, aber viele andere Anwendungen nicht. Es ist am besten, diese Funktion niemals zu benutzen.

    
Puppy 13.12.2012 13:04
quelle
-2

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.

    
Christian Rau 13.12.2012 13:15
quelle

Tags und Links