Ich versuche zu verstehen, wie es std::unique_ptr
funktioniert und dafür habe ich dieses Dokument gefunden. Der Autor geht von folgendem Beispiel aus:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
Was mich verwirrt, ist das in dieser Zeile
unique_ptr<int> uptr (new int(3));
Wir verwenden Integer als Argument (zwischen runden Klammern) und hier
unique_ptr<double> uptr2 (pd);
Wir haben einen Zeiger als Argument verwendet. Macht es einen Unterschied?
Was mir auch nicht klar ist, ist, wie sich auf diese Weise deklarierte Zeiger von den auf "normale" Weise deklarierten Zeigern unterscheiden.
c++
pointers
std
unique-ptr
römisch
quelle
quelle
new int(3)
Gibt einen Zeiger auf das Neue zurückint
, genau wiepd
ein Zeiger auf das Neuedouble
.Antworten:
Der Konstruktor von
unique_ptr<T>
akzeptiert einen Rohzeiger auf ein Objekt vom TypT
(also akzeptiert er aT*
).Im ersten Beispiel:
Der Zeiger ist das Ergebnis eines
new
Ausdrucks, während im zweiten Beispiel:Der Zeiger wird in der
pd
Variablen gespeichert .Konzeptionell ändert sich nichts (Sie konstruieren einen
unique_ptr
aus einem Rohzeiger), aber der zweite Ansatz ist möglicherweise gefährlicher, da Sie beispielsweise Folgendes tun könnten:Somit gibt es zwei eindeutige Zeiger, die dasselbe Objekt effektiv einkapseln (wodurch die Semantik eines eindeutigen Zeigers verletzt wird ).
Aus diesem Grund ist das erste Formular zum Erstellen eines eindeutigen Zeigers nach Möglichkeit besser. Beachten Sie, dass wir in C ++ 14 Folgendes tun können:
Welches ist klarer und sicherer. Nun zu Ihrem Zweifel:
Intelligente Zeiger sollen den Objektbesitz modellieren und automatisch dafür sorgen, dass das spitze Objekt zerstört wird, wenn der letzte (intelligente, besitzende) Zeiger auf dieses Objekt außerhalb des Gültigkeitsbereichs liegt.
Auf diese Weise müssen Sie sich nicht daran erinnern, dass Sie
delete
Objekte dynamisch zugewiesen haben - der Destruktor des intelligenten Zeigers erledigt dies für Sie - und Sie müssen sich auch keine Gedanken darüber machen, ob Sie einen (baumelnden) Zeiger nicht auf ein bereits zerstörtes Objekt dereferenzieren:Jetzt
unique_ptr
handelt es sich um einen intelligenten Zeiger, der die eindeutige Eigentümerschaft modelliert. Dies bedeutet, dass zu jedem Zeitpunkt in Ihrem Programm nur ein (besitzender) Zeiger auf das spitze Objekt vorhanden sein darf - daher kann erunique_ptr
nicht kopiert werden.Solange Sie Smart Pointer so verwenden, dass der implizite Vertrag, den Sie einhalten müssen, nicht verletzt wird, haben Sie die Garantie, dass kein Speicher verloren geht, und die ordnungsgemäße Eigentumsrichtlinie für Ihr Objekt wird durchgesetzt. Rohe Zeiger geben Ihnen diese Garantie nicht.
quelle
model object ownership
, dasinteger leak
im Code oderenforcing ownership policy for object
. Könnten Sie bitte Themen / Ressourcen vorschlagen, um diese Konzepte zu lernen?unique_ptr
, ohne einen Fehler zu bekommen:The text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template.
obwohl ich#include <utility>
und habe#include <memory>
. Irgendein Rat?Es gibt keinen Unterschied in der Arbeit in beiden Konzepten der Zuweisung zu unique_ptr.
ist ähnlich wie
Hier löscht unique_ptr automatisch den von belegten Speicherplatz
uptr
.Wenn Sie eine Ganzzahl im Heap-Bereich erstellen (mit einem neuen Schlüsselwort oder malloc ), müssen Sie diesen Speicher selbst löschen (mit delete bzw. free ).
Im folgenden Code
Hier müssen Sie heapInt löschen , wenn es mit fertig ist. Wenn es nicht gelöscht wird, tritt ein Speicherverlust auf.
Um solche Speicherlecks zu vermeiden, wird unique_ptr verwendet, wobei unique_ptr automatisch den von heapInt belegten Speicherplatz löscht, wenn der Gültigkeitsbereich verlassen wird. So müssen Sie nicht löschen oder frei für unique_ptr.
quelle
Einzigartige Zeiger zerstören garantiert das von ihnen verwaltete Objekt, wenn sie den Gültigkeitsbereich verlassen. http://en.cppreference.com/w/cpp/memory/unique_ptr
In diesem Fall:
pd
wird zerstört, wennuptr2
der Geltungsbereich überschritten wird. Dies erleichtert die Speicherverwaltung durch automatisches Löschen.Der Fall von
unique_ptr<int> uptr (new int(3));
ist nicht anders, außer dass der Rohzeiger hier keiner Variablen zugewiesen ist.quelle
Von cppreference , einer der
std::unique_ptr
Konstrukteure istexplizites unique_ptr (Zeiger p) noexcept;
Ein neues zu erstellen bedeutet
std::unique_ptr
also, einen Zeiger an seinen Konstruktor zu übergeben.Oder es ist das gleiche wie
Der Unterschied ist, dass Sie nach der Verwendung nicht aufräumen müssen. Wenn Sie nicht verwenden
std::unique_ptr
(Smart Pointer), müssen Sie es so löschenWenn Sie es nicht mehr benötigen, führt dies zu einem Speicherverlust.
quelle