Auf jeden Fall eine +1, weil ich gesehen habe, dass so viele Leute das falsch verstanden haben. Es ist eine gute Frage.
Twokats
Bitte lesen Sie auch den entsprechenden Artikel. Diese Frage wird hier von der anderen Seite betrachtet. Kann hilfreich sein, um mehr über auto_ptr- und STL-Container zu erfahren. stackoverflow.com/questions/8630552/…
movesemantisch und unique_ptrwurden entwickelt, um die damit verbundenen Probleme zu vermeiden auto_ptr. In C ++ 03 war die Sprache nicht leistungsfähig genug, um eine solche Klasse zu schreiben auto_ptr, die sich in allen Szenarien korrekt und sicher verhält, da der Compiler und die Sprache nicht in der Lage waren, l- und r-Werte zu unterscheiden, sodass einige "Hacks" verwendet wurden, um das gewünschte Verhalten zu erzielen meistens.
Phil 1970
Schöner Artikel: STL-Container und Auto_ptrs - Warum sie sich nicht mischen quantstart.com/articles/…
alfC
Antworten:
124
Der C ++ - Standard besagt, dass ein STL-Element "kopierkonstruierbar" und "zuweisbar" sein muss. Mit anderen Worten, ein Element muss zugewiesen oder kopiert werden können und die beiden Elemente sind logisch unabhängig. std::auto_ptrerfüllt diese Anforderung nicht.
Nehmen Sie zum Beispiel diesen Code:
class X
{};
std::vector<std::auto_ptr<X>> vecX;
vecX.push_back(new X);
std::auto_ptr<X> pX = vecX[0];// vecX[0] is assigned NULL.
Sie sollten auch die Boost-Zeiger-Container berücksichtigen, wenn Sie keinen gemeinsamen Besitz benötigen.
Me22
4
unique_ptrDas Kopieren ist ebenfalls nicht zulässig, sodass bestimmte STL-Vorgänge nur dann ordnungsgemäß funktionieren, wenn sie die Verschiebungssemantik verwenden können.
Mike Weller
4
"Um diese Einschränkung zu überwinden, sollten Sie std::unique_ptrFolgendes verwenden :": Diese Klassenvorlage kann nur aufgrund der Verschiebungssemantik existieren (ihre Spezifikation erfordert rWertreferenzen), daher ist grundsätzlich C ++ 11 erforderlich. Der C ++ 11-Standard besagt jedoch (und verwandt) nicht mehr, dass ein STL-Elementtyp "kopierkonstruierbar" und "zuweisbar" sein muss. bewegungskonstruierbar und bewegungszuweisbar zu sein, reicht aus. In der Tat sind unique_ptrInstanzen nur bewegungskonstruierbar und verschiebungszuweisbar. Aber auto_ptrInstanzen auch! Infolgedessen können Sie in C ++ 11 das tun, auto_ptrwas Sie können unique_ptr.
Marc van Leeuwen
@MarcvanLeeuwen, es sei denn, Sie resetund releasenach Bedarf
Ratschenfreak
2
@ Ratchetfreak: Hmm, ich verstehe nicht. Was? "es sei denn du resetund release", ich sehe nicht, wie das auf irgendetwas in meinem Kommentar zutrifft. Beachten Sie, dass beide auto_ptrund unique_ptrbeide Methoden haben und in beiden Fällen dasselbe tun.
Marc van Leeuwen
66
Die Kopiersemantik von auto_ptrist nicht mit den Containern kompatibel.
Insbesondere werden beim Kopieren in ein auto_ptranderes Objekt nicht zwei gleiche Objekte erstellt, da eines seinen Besitz des Zeigers verloren hat.
Insbesondere auto_ptrbewirkt das Kopieren eines, dass eine der Kopien den Zeiger loslässt. Welche davon im Container verbleibt, ist nicht definiert. Daher können Sie zufällig den Zugriff auf Zeiger verlieren, wenn Sie auto_ptrsin den Containern speichern .
Weil ich denke, dass er sich in den letzten fast zwei Jahren wahrscheinlich mit dem vorliegenden Problem befasst hat.
Welpe
27
@DeadMG: Ja, du bist richtig. Aber das war nicht mein Ziel. Wenn irgendwann jemand zu diesem Thread kommt und etwas darüber lernen möchte auto_ptr, sind diese Links hilfreich, da bin ich mir sicher.
Lazer
Es gibt viele Duplikate, die neuer sind.
Welpe
8
@DeadMG: Diese Frage wurde nicht als Duplikat geschlossen und kann daher erweitert werden. Lazer sagte, was hier vorher nicht gesagt wurde. Ich denke, er ist zufällig gekommen.
Sebastian Mach
Die Erklärungen im zweiten Link, die das Problem nach dem Anruf analysieren sort(), sind klarer als alle Antworten hier.
Chaosink
17
Die STL-Container müssen in der Lage sein, die darin gespeicherten Elemente zu kopieren, und müssen so ausgelegt sein, dass das Original und die Kopie gleichwertig sind. Auto-Pointer-Objekte haben einen völlig anderen Vertrag, wobei durch das Kopieren eine Eigentumsübertragung entsteht. Dies bedeutet, dass Container mit auto_ptr je nach Verwendung ein seltsames Verhalten aufweisen.
Es gibt eine detaillierte Beschreibung dessen, was in Effective STL (Scott Meyers) Punkt 8 schief gehen kann, und eine nicht so detaillierte Beschreibung in Effective C ++ (Scott Meyers) Punkt 13.
STL-Container speichern Kopien der enthaltenen Artikel. Wenn ein auto_ptr kopiert wird, wird der alte ptr auf null gesetzt. Viele Containermethoden sind durch dieses Verhalten fehlerhaft.
Aber wenn Sie unique_ptr verwenden, erhalten Sie so ziemlich das Gleiche, da nur ein unique_ptr das Eigentum an dem Objekt haben kann?
Tracer
2
@Tracer kann unique_ptrwie jedes richtige C ++ 11-Objekt das Eigentum an seiner Ressource nur übertragen, wenn es verschoben oder zugewiesen wird. Dadurch wird sichergestellt, dass der Programmierer absichtlich einen std::move(sourceObject)oder einen temporären Wert übergeben muss , anstatt einen l-Wert zu übergeben und ihn unbeabsichtigt / unvorhersehbar mutieren zu lassen die Kopieraufgabe ... die, wie hier ausführlich betont, ein Kernproblem von war auto_ptr.
underscore_d
4
Die Norm C ++ 03 (ISO-IEC 14882-2003) besagt in Abschnitt 20.4.5 Absatz 3:
[...] [ Hinweis: [...] auto_ptr erfüllt nicht die CopyConstructible- und Assignable-Anforderungen für Standard Library-Containerelemente. Das Instanziieren eines Standard Library-Containers mit auto_ptr führt daher zu einem undefinierten Verhalten. - Endnote ]
Der C ++ 11-Standard (ISO-IEC 14882-2011) besagt in Anhang D.10.1 Absatz 3:
[...]
Hinweis: [...] Instanzen von auto_ptr erfüllen die Anforderungen von MoveConstructible und MoveAssignable, jedoch nicht die Anforderungen von CopyConstructible und CopyAssignable. - Endnote]
Die Norm C ++ 14 (ISO-IEC 14882-2014) besagt in Anhang C.4.2 Anhang D: Kompatibilitätsmerkmale:
Änderung : Die Klassenvorlagen auto_ptr, unary_function und binary_function, die Funktionsvorlagen random_shuffle und die Funktionsvorlagen (und ihre Rückgabetypen) ptr_fun, mem_fun, mem_fun_ref, bind1st und bind2nd sind nicht definiert. Begründung : Ersetzt durch neue Funktionen. Auswirkung auf die ursprüngliche Funktion : Gültiger C ++ 2014-Code, der diese Klassenvorlagen und Funktionsvorlagen verwendet, kann in diesem internationalen Standard möglicherweise nicht kompiliert werden.
move
semantisch undunique_ptr
wurden entwickelt, um die damit verbundenen Probleme zu vermeidenauto_ptr
. In C ++ 03 war die Sprache nicht leistungsfähig genug, um eine solche Klasse zu schreibenauto_ptr
, die sich in allen Szenarien korrekt und sicher verhält, da der Compiler und die Sprache nicht in der Lage waren, l- und r-Werte zu unterscheiden, sodass einige "Hacks" verwendet wurden, um das gewünschte Verhalten zu erzielen meistens.Antworten:
Der C ++ - Standard besagt, dass ein STL-Element "kopierkonstruierbar" und "zuweisbar" sein muss. Mit anderen Worten, ein Element muss zugewiesen oder kopiert werden können und die beiden Elemente sind logisch unabhängig.
std::auto_ptr
erfüllt diese Anforderung nicht.Nehmen Sie zum Beispiel diesen Code:
Um diese Einschränkung zu überwinden, sollten Sie die Verwendung
std::unique_ptr
,std::shared_ptr
oderstd::weak_ptr
intelligente Zeiger oder den Boost - Äquivalente , wenn Sie C ++ nicht 11. Hier ist die Dokumentation zur Boost-Bibliothek für diese intelligenten Zeiger.quelle
unique_ptr
Das Kopieren ist ebenfalls nicht zulässig, sodass bestimmte STL-Vorgänge nur dann ordnungsgemäß funktionieren, wenn sie die Verschiebungssemantik verwenden können.std::unique_ptr
Folgendes verwenden :": Diese Klassenvorlage kann nur aufgrund der Verschiebungssemantik existieren (ihre Spezifikation erfordert rWertreferenzen), daher ist grundsätzlich C ++ 11 erforderlich. Der C ++ 11-Standard besagt jedoch (und verwandt) nicht mehr, dass ein STL-Elementtyp "kopierkonstruierbar" und "zuweisbar" sein muss. bewegungskonstruierbar und bewegungszuweisbar zu sein, reicht aus. In der Tat sindunique_ptr
Instanzen nur bewegungskonstruierbar und verschiebungszuweisbar. Aberauto_ptr
Instanzen auch! Infolgedessen können Sie in C ++ 11 das tun,auto_ptr
was Sie könnenunique_ptr
.reset
undrelease
nach Bedarfreset
undrelease
", ich sehe nicht, wie das auf irgendetwas in meinem Kommentar zutrifft. Beachten Sie, dass beideauto_ptr
undunique_ptr
beide Methoden haben und in beiden Fällen dasselbe tun.Die Kopiersemantik von
auto_ptr
ist nicht mit den Containern kompatibel.Insbesondere werden beim Kopieren in ein
auto_ptr
anderes Objekt nicht zwei gleiche Objekte erstellt, da eines seinen Besitz des Zeigers verloren hat.Insbesondere
auto_ptr
bewirkt das Kopieren eines, dass eine der Kopien den Zeiger loslässt. Welche davon im Container verbleibt, ist nicht definiert. Daher können Sie zufällig den Zugriff auf Zeiger verlieren, wenn Sieauto_ptrs
in den Containern speichern .quelle
Zwei super ausgezeichnete Artikel zu diesem Thema:
quelle
auto_ptr
, sind diese Links hilfreich, da bin ich mir sicher.sort()
, sind klarer als alle Antworten hier.Die STL-Container müssen in der Lage sein, die darin gespeicherten Elemente zu kopieren, und müssen so ausgelegt sein, dass das Original und die Kopie gleichwertig sind. Auto-Pointer-Objekte haben einen völlig anderen Vertrag, wobei durch das Kopieren eine Eigentumsübertragung entsteht. Dies bedeutet, dass Container mit auto_ptr je nach Verwendung ein seltsames Verhalten aufweisen.
Es gibt eine detaillierte Beschreibung dessen, was in Effective STL (Scott Meyers) Punkt 8 schief gehen kann, und eine nicht so detaillierte Beschreibung in Effective C ++ (Scott Meyers) Punkt 13.
quelle
STL-Container speichern Kopien der enthaltenen Artikel. Wenn ein auto_ptr kopiert wird, wird der alte ptr auf null gesetzt. Viele Containermethoden sind durch dieses Verhalten fehlerhaft.
quelle
unique_ptr
wie jedes richtige C ++ 11-Objekt das Eigentum an seiner Ressource nur übertragen, wenn es verschoben oder zugewiesen wird. Dadurch wird sichergestellt, dass der Programmierer absichtlich einenstd::move(sourceObject)
oder einen temporären Wert übergeben muss , anstatt einen l-Wert zu übergeben und ihn unbeabsichtigt / unvorhersehbar mutieren zu lassen die Kopieraufgabe ... die, wie hier ausführlich betont, ein Kernproblem von warauto_ptr
.Die Norm C ++ 03 (ISO-IEC 14882-2003) besagt in Abschnitt 20.4.5 Absatz 3:
Der C ++ 11-Standard (ISO-IEC 14882-2011) besagt in Anhang D.10.1 Absatz 3:
Die Norm C ++ 14 (ISO-IEC 14882-2014) besagt in Anhang C.4.2 Anhang D: Kompatibilitätsmerkmale:
quelle