Antworten:
Der direkte Ersatz für auto_ptr
(oder das, was einem sowieso am nächsten kommt) ist unique_ptr
. Was das "Problem" betrifft, ist es ziemlich einfach: auto_ptr
Überträgt das Eigentum, wenn es zugewiesen wird. unique_ptr
überträgt auch das Eigentum, aber dank der Kodifizierung der Bewegungssemantik und der Magie der Wertreferenzen kann dies wesentlich natürlicher geschehen. Es "passt" auch wesentlich besser zum Rest der Standardbibliothek (obwohl ein Teil davon fairerweise darauf zurückzuführen ist, dass der Rest der Bibliothek geändert wurde, um die Verschiebungssemantik zu berücksichtigen, anstatt immer kopiert werden zu müssen).
Die Namensänderung ist auch (IMO) eine willkommene - auto_ptr
sagt nicht wirklich viel darüber aus, was sie zu automatisieren versucht, wohingegen unique_ptr
eine ziemlich vernünftige (wenn auch knappe) Beschreibung dessen, was bereitgestellt wird.
auto_ptr
Namen: auto schlägt automatisch wie in der automatischen Variablen vor und bezieht sich auf eine Sache, auto_ptr
die Folgendes bewirkt: Zerstören der verwalteten Ressource in ihrem Destruktor (wenn sie außerhalb des Gültigkeitsbereichs liegt).
auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…
std::sort
hat keine Spezialisierung für unique_ptr
. Stattdessen wurde es neu spezifiziert, um niemals zu kopieren. So funktioniertauto_ptr
eigentlich mit der Moderne . C ++ 98/03 ist hier jedoch nur ein Beispielalgorithmus: Jeder generische Algorithmus (vom Standard bereitgestellt oder vom Benutzer geschrieben), der davon ausgeht, dass die Kopiersyntax eine Kopiersemantik aufweist, weist bei Verwendung wahrscheinlich einen Laufzeitfehler auf , da er sich stillschweigend bewegt mit Kopie - Syntax. Das Problem ist viel größer als nur . sort
sort
auto_ptr
auto_ptr
sort
Ich fand die vorhandenen Antworten großartig, aber aus dem PoV der Zeiger. IMO, eine ideale Antwort sollte die perspektivische Antwort des Benutzers / Programmierers haben.
Das erste zuerst (wie Jerry Coffin in seiner Antwort angedeutet hat)
shared_ptr: Wenn Sie Bedenken haben, Ressourcen / Speicher freizugeben UND wenn Sie mehr als eine Funktion haben, die das Objekt AT-DIFFERENT mal verwenden könnte, dann gehen Sie zu shared_ptr.
Stellen Sie sich bei DIFFERENT-Times eine Situation vor, in der das Objekt-ptr in mehreren Datenstrukturen gespeichert ist und später darauf zugegriffen wird. Ein weiteres Beispiel sind natürlich mehrere Threads.
unique_ptr: Wenn Sie nur Speicher freigeben und der Zugriff auf das Objekt SEQUENTIAL ist, wählen Sie unique_ptr.
Mit SEQUENTIAL meine ich, dass zu jedem Zeitpunkt von einem Kontext aus auf das Objekt zugegriffen wird. ZB ein Objekt, das erstellt und unmittelbar nach der Erstellung durch den Ersteller verwendet wurde. Nach der Erstellung wird das Objekt in der FIRST- Datenstruktur gespeichert . Dann wird entweder das Objekt nach der ONE-Datenstruktur zerstört oder in die SECOND- Datenstruktur verschoben .
In dieser Zeile werde ich Shared / Unique _ptr als Smart-Pointer bezeichnen. (auto_ptr ist auch ein Smart-Pointer, ABER aufgrund von Designfehlern, für die sie veraltet sind und auf die ich in den nächsten Zeilen hinweisen werde, sollten sie nicht mit Smart-Pointer gruppiert werden.)
Der wichtigste Grund, warum auto_ptr zugunsten von smart-pointer veraltet war, ist die Zuweisungssemantik. Wenn dies nicht der Fall gewesen wäre, hätten sie alle neuen Extras der Verschiebungssemantik zu auto_ptr hinzugefügt, anstatt sie zu verwerfen. Da die Zuweisungssemantik am wenigsten beliebt war, wollten sie, dass diese Funktion wegfällt. Da jedoch Code geschrieben ist, der diese Semantik verwendet (die das Standardkomitee nicht ändern kann), mussten sie stattdessen auto_ptr loslassen es zu ändern.
Über den Link: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
Art der von unqiue_ptr unterstützten Zuweisungen
Von: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Art der von auto_ptr unterstützten Zuweisungen
Nun zu dem Grund, warum die Kopieraufgabe selbst so unbeliebt war, habe ich diese Theorie:
Das unbeabsichtigte Verhalten ist wirklich unbeliebt und daher die Abneigung gegen auto_ptr.
(Für die 3.1415926536% der Programmierer, die absichtlich das Eigentum übertragen möchten, gab C ++ 11 ihnen std :: move (), was ihre Absicht für alle Praktikanten, die den Code lesen und pflegen werden, kristallklar machte.)
auto_ptr
Werte auf dasselbe Objekt verweisen (da sie kein gemeinsames Eigentum geben, hinterlässt der erste, der stirbt, dem anderen ein tödliches Erbe; dies gilt auch für die unique_ptr
Verwendung), können Sie vorschlagen, was in beabsichtigt war die verbleibenden 96,8584073465% aller Nutzung?
*a=*b;
Hier wird nur der Wert von b nach a kopiert. Ich hoffe, dass das Eigentum an a und b immer noch bei denselben Personen liegt. Sie haben erwähnt, dass das Eigentum übertragen wird. Wie es sein wird?
auto_ptr
Objekt selbst. Die Zuordnung zu / von seinem angegebenen Wert hat weder Auswirkungen noch Relevanz für das Eigentum. Ich hoffe du benutzt noch nicht auto_ptr
?
Noch eine andere Art, den Unterschied zu erklären ...
Funktionell ist C ++ 11 std::unique_ptr
das "Feste" std::auto_ptr
: Beide sind geeignet, wenn zu einem beliebigen Zeitpunkt während der Ausführung ein einziger Smart-Pointer-Eigentümer für ein Objekt vorhanden sein sollte, auf das verwiesen wird.
Der entscheidende Unterschied besteht in der Erstellung oder Zuweisung von Kopien von einem anderen nicht ablaufenden Smart Pointer (siehe folgende =>
Zeilen):
std::auto_ptr<T> ap(...);
std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership
=> std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release());
ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL
std::unique_ptr<T> up(...);
std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership
=> std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
Oben ap3
"stiehlt" er leise das Eigentum an *ap
und verlässt ap
es auf a nullptr
, und das Problem ist, dass dies zu leicht passieren kann, ohne dass der Programmierer über seine Sicherheit nachgedacht hat.
Wenn ein class
/ beispielsweise struct
ein std::auto_ptr
Mitglied hat, wird release
beim Erstellen einer Kopie einer Instanz der Zeiger der zu kopierenden Instanz angezeigt. Dies ist eine seltsame und gefährlich verwirrende Semantik, da das Kopieren normalerweise nichts ändert. Es ist für den Klassen- / Strukturautor leicht, die Freigabe des Zeigers zu übersehen, wenn er über Invarianten und den Status nachdenkt, und folglich versehentlich zu versuchen, den Smart-Zeiger zu dereferenzieren, während er null ist, oder einfach noch nicht den erwarteten Zugriff / Besitz der referenzierten Daten zu haben.
auto_ptr kann nicht in STL-Containern verwendet werden, da es einen Kopierkonstruktor hat, der die Anforderungen des Containers CopyConstructible nicht erfüllt . unique_ptr implementiert keinen Kopierkonstruktor, daher verwenden Container alternative Methoden. unique_ptr kann in Containern verwendet werden und ist für Standardalgorithmen schneller als shared_ptr.
#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>
using namespace std;
int main() {
cout << boolalpha;
cout << "is_copy_constructible:" << endl;
cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;
vector<int> i_v;
i_v.push_back(1);
cout << "i_v=" << i_v[0] << endl;
vector<int> i_v2=i_v;
cout << "i_v2=" << i_v2[0] << endl;
vector< unique_ptr<int> > u_v;
u_v.push_back(unique_ptr<int>(new int(2)));
cout << "u_v=" << *u_v[0] << endl;
//vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true
vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved
cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;
vector< shared_ptr<int> > s_v;
shared_ptr<int> s(new int(3));
s_v.push_back(s);
cout << "s_v=" << *s_v[0] << endl;
vector< shared_ptr<int> > s_v2=s_v;
cout << "s_v2=" << *s_v2[0] << endl;
vector< auto_ptr<int> > a_v; //USAGE ERROR
return 0;
}
>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
vector< auto_ptr<int> > a_v; //USAGE ERROR
^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3