Warum ist es falsch zu verwenden std::auto_ptr<>
mit Standardcontainern?
Warum ist es falsch, std::auto_ptr mit Standardcontainern zu verwenden?
Uhall
Der C++-Standard besagt, dass ein STL-Element „kopierbar“ und „zuweisbar“ sein muss. Das heißt, ein Element muss zuweisbar oder kopierbar sein und die beiden Elemente müssen logisch unabhängig sein. std::auto_ptr
erfü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.
Um diese Einschränkung zu überwinden, sollten Sie die verwenden std::unique_ptr
, std::shared_ptr
oder std::weak_ptr
Smart Pointer oder die Boost-Äquivalente, wenn Sie C++11 nicht haben. Hier ist die Dokumentation der Boost-Bibliothek für diese intelligenten Zeiger.
-
Sie sollten auch die Boost-Zeiger-Container in Betracht ziehen, wenn Sie kein gemeinsames Eigentum benötigen.
– ich22
10. September 2009 um 16:34 Uhr
-
unique_ptr
verbietet auch das Kopieren, sodass bestimmte STL-Operationen nicht korrekt funktionieren, es sei denn, sie können ihre Bewegungssemantik verwenden.– Mike Weller
1. Juli 2013 um 9:54 Uhr
-
“Um diese Einschränkung zu überwinden, sollten Sie die verwenden
std::unique_ptr
“: Diese Klassenvorlage kann nur aufgrund der Bewegungssemantik existieren (ihre Spezifikation erfordert Rvalue-Referenzen), daher ist grundsätzlich C++11 erforderlich. Der C++11-Standard sagt jedoch (und damit zusammenhängend) nicht mehr, dass ein STL-Elementtyp sein muss „kopierkonstruierbar“ und „zuweisbar“, es reicht aus, bewegungskonstruierbar und bewegungszuweisbar zu seinunique_ptr
Instanzen sind nur bewegungskonstruierbar und bewegungszuweisbar. Aber so sindauto_ptr
Fälle! Infolgedessen können Sie in C++ 11 mitauto_ptr
was du damit machen kannstunique_ptr
.– Marc van Leeuwen
27. August 2014 um 9:26 Uhr
-
@MarcvanLeeuwen, es sei denn, Sie
reset
undrelease
wie benötigt– Ratschenfreak
3. September 2014 um 7:47 Uhr
-
@ratchetfreak: Hmm, verstehe ich nicht. Was? “Außer du
reset
undrelease
“Ich sehe nicht, wie das auf irgendetwas in meinem Kommentar zutrifft. Beachten Sie, dass beides giltauto_ptr
undunique_ptr
haben diese beiden Methoden, und sie tun in beiden Fällen dasselbe.– Marc van Leeuwen
3. September 2014 um 9:05 Uhr
Frank Krüger
Die Semantik kopieren von auto_ptr
sind mit den Behältern nicht kompatibel.
Insbesondere das Kopieren eines auto_ptr
zu einem anderen erstellt nicht zwei gleiche Objekte, da eines seinen Besitz des Zeigers verloren hat.
Genauer gesagt, das Kopieren einer auto_ptr
bewirkt, dass eine der Kopien den Zeiger loslässt. Was davon im Behälter verbleibt, ist nicht definiert. Daher können Sie zufällig den Zugriff auf Zeiger verlieren, wenn Sie speichern auto_ptrs
in den Behältern.
Zwei super exzellente Artikel zum Thema:
-
Weil ich denke, dass er sich in den dazwischenliegenden fast zwei Jahren wahrscheinlich mit dem vorliegenden Problem befasst hat.
– Hündchen
25. Juni 2010 um 20:31 Uhr
-
@DeadMG: Ja, du hast Recht. Aber das war nicht meine Absicht. Falls jemand irgendwann mal in diesen Thread kommt und sich informieren will
auto_ptr
und so, diese Links werden hilfreich sein, da bin ich mir sicher.– Laser
25. Juni 2010 um 20:44 Uhr
-
Es gibt viele Duplikate, die neuer sind.
– Hündchen
25. Juni 2010 um 21:23 Uhr
-
@DeadMG: Diese Frage wurde nicht als Duplikat geschlossen und kann daher erweitert werden. Lazer sagte, was hier vorher nicht gesagt wurde. Ich schätze, er kam zufällig vorbei.
– Sebastian Mach
18. November 2011 um 16:21 Uhr
-
Die Erläuterungen im zweiten Link, die das Problem nach Aufruf analysieren
sort()
sind klarer als alle Antworten hier.– Chaos
1. Mai 2020 um 19:35 Uhr
Garth Gilmour
Die STL-Container müssen in der Lage sein, die darin gespeicherten Artikel zu kopieren, und sind so konzipiert, dass das Original und die Kopie gleichwertig sind. Auto-Pointer-Objekte haben einen ganz anderen Vertrag, wobei das Kopieren einen Eigentumsübergang bewirkt. Das bedeutet, dass Container von auto_ptr je nach Verwendung ein seltsames Verhalten aufweisen.
Es gibt eine detaillierte Beschreibung dessen, was schief gehen kann, in Punkt 8 von Effektivem STL (Scott Meyers) und auch eine nicht so detaillierte Beschreibung in Punkt 13 von Effektivem C++ (Scott Meyers).
STL-Container speichern Kopien enthaltener Elemente. Wenn ein auto_ptr kopiert wird, setzt er den alten ptr auf null. Viele Containermethoden werden durch dieses Verhalten beschädigt.
-
Aber wenn Sie unique_ptr verwenden, erhalten Sie so ziemlich dasselbe, da nur ein unique_ptr das Eigentum an dem Objekt haben kann?
– Tracer
11. Juli 2014 um 6:56 Uhr
-
@ Tracer
unique_ptr
Wie jedes richtige C++ 11-Objekt kann das Eigentum an seiner Ressource nur übertragen werden, wenn es verschoben oder zugewiesen wird, wodurch sichergestellt wird, dass der Programmierer absichtlich eine übergeben mussstd::move(sourceObject)
oder eine vorübergehende, anstatt eine zu übergeben Wert und unintuitiv / unvorhersehbar durch die Kopierzuweisung mutiert … was, wie hier ausführlich betont wird, ein Kernproblem von warauto_ptr
.– Unterstrich_d
23. Februar 2016 um 0:15 Uhr
C++03-Standard (ISO-IEC 14882-2003) heißt es in Ziffer 20.4.5 Absatz 3:
[…]
[Note: […]auto_ptr erfüllt nicht die CopyConstructible- und Assignable-Anforderungen für Containerelemente der Standardbibliothek, und daher führt die Instanziierung eines Standardbibliothekscontainers mit einem auto_ptr zu undefiniertem Verhalten. — Endnote]
C++11-Standard (ISO-IEC 14882-2011) heißt es in Anhang D.10.1 Absatz 3:
[…]
Notiz: […] Instanzen von auto_ptr erfüllen die Anforderungen von MoveConstructible und MoveAssignable, aber nicht die Anforderungen von CopyConstructible und CopyAssignable. — Endnote]
C++14-Standard (ISO-IEC 14882-2014) heißt es in Anhang C.4.2 Anhang D: Kompatibilitätsmerkmale:
ÄndernHinweis: 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: Durch neue Funktionen ersetzt.
Auswirkung auf das ursprüngliche Merkmal: Gültiger C ++ 2014-Code, der diese Klassenvorlagen und Funktionsvorlagen verwendet, kann möglicherweise nicht in dieser Internationalen Norm kompiliert werden.
-
Aber wenn Sie unique_ptr verwenden, erhalten Sie so ziemlich dasselbe, da nur ein unique_ptr das Eigentum an dem Objekt haben kann?
– Tracer
11. Juli 2014 um 6:56 Uhr
-
@ Tracer
unique_ptr
Wie jedes richtige C++ 11-Objekt kann das Eigentum an seiner Ressource nur übertragen werden, wenn es verschoben oder zugewiesen wird, wodurch sichergestellt wird, dass der Programmierer absichtlich eine übergeben mussstd::move(sourceObject)
oder eine vorübergehende, anstatt eine zu übergeben Wert und unintuitiv / unvorhersehbar durch die Kopierzuweisung mutiert … was, wie hier ausführlich betont wird, ein Kernproblem von warauto_ptr
.– Unterstrich_d
23. Februar 2016 um 0:15 Uhr
Definitiv ein +1 dafür, weil ich gesehen habe, dass so viele Leute das falsch verstanden haben. Es ist eine großartige Frage.
– Zweikats
7. November 2008 um 20:42 Uhr
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/…
– Nickolay
29. Dezember 2011 um 11:59 Uhr
Häufig gestellte Fragen zu C++: Kann ich einen Container mit intelligenten Zeigern auf meine Objekte haben?
– Amro
18. Mai 2012 um 1:44 Uhr
move
semantisch uunique_ptr
wurden entwickelt, um die damit verbundenen Probleme zu vermeidenauto_ptr
. In C++ 03 war die Sprache nicht mächtig genug, um eine Klasse wie zu schreibenauto_ptr
die sich in allen Szenarien korrekt und sicher verhalten, da der Compiler und die Sprache nicht in der Lage waren, l- und r-Werte zu unterscheiden, sodass einige “Hacks” verwendet wurden, um die meiste Zeit das gewünschte Verhalten zu erzielen.– Phil1970
12. Mai 2017 um 3:22 Uhr
Schöner Artikel: STL-Container und Auto_ptrs – Warum sie nicht mischen quantstart.com/articles/…
– alfC
8. Juni 2020 um 9:08 Uhr