2013-06-03 6 views
29

Ich versuche zu verstehen, wie std::unique_ptr funktioniert und dafür habe ich this Dokument gefunden. Der Autor geht von folgendem Beispiel:Wie deklariert man std :: unique_ptr und was nützt es?

#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 mir verwirrend ist, dass

in dieser Linie
unique_ptr<int> uptr (new int(3)); 

Wir integer als Argument verwenden (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 Zeiger, die auf diese Weise deklariert werden, sich von den "normal" deklarierten Zeigern unterscheiden werden.

+4

'new int (3)' gibt einen Zeiger auf den neuen 'int' zurück, genau wie' pd' ein Zeiger auf den neuen 'double' war. –

Antwort

3

Eindeutige Zeiger werden garantiert zerstört, wenn Sie den Bereich verlassen. http://en.cppreference.com/w/cpp/memory/unique_ptr

Im Fall:

unique_ptr<double> uptr2 (pd); 

pd zerstört wird, wenn Sie den Gültigkeitsbereich verlassen. Dies erleichtert die Speicherverwaltung durch automatisches Löschen.

dann Falle unique_ptr<int> uptr (new int(3)); unterscheidet sich nicht, außer dass roher Zeiger nicht hier auf jede Variable

zugeordnet ist
35

Konstruktor unique_ptr<T> akzeptiert einen rohen Zeiger auf ein Objekt des Typs T (so, es nimmt ein T*).

Im ersten Beispiel:

unique_ptr<int> uptr (new int(3)); 

Der Zeiger ist das Ergebnis eines new Expression, während im zweiten Beispiel:

unique_ptr<double> uptr2 (pd); 

Der Zeiger wird in dem pd Variable gespeichert.

Konzeptionell ändert sich nichts (Sie unique_ptr aus einem rohen Zeiger bauen), aber der zweite Ansatz ist potenziell gefährlich, da es Ihnen erlauben würde, zum Beispiel zu tun:

unique_ptr<double> uptr2 (pd); 
// ... 
unique_ptr<double> uptr3 (pd); 

So hat zwei eindeutige Zeiger, die das gleiche Objekt effektiv einkapseln (und somit die Semantik eines eindeutigen Zeigers verletzen).

Aus diesem Grund ist die erste Form zum Erstellen eines eindeutigen Zeigers, wenn möglich, besser. Beachten Sie, dass wir in C++ 14 können:

unique_ptr<int> p = make_unique<int>(42); 

Das ist sowohl klarer als auch sicherer.Jetzt über diese Zweifel von Ihnen:

What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

Intelligente Zeiger sollen Objektbesitz modellieren, und automatisch den spitzen Gegenstand zu zerstören kümmern, wenn die letzten (smart, den Besitz) Zeiger auf dieses Objekt den Gültigkeitsbereich fallen.

Auf diese Weise müssen Sie dynamisch zugewiesen tun delete auf Objekte nicht mehr erinnern - der Destruktor des Smart-Pointer wird für Sie das tun - noch zu kümmern, ob werden Sie nicht dereferenzieren ein (baumelnden) Zeiger auf ein Objekt, das wurde bereits zerstört: ein (Besitz) Zeiger auf den spitzen Gegenstand nur

{ 
    unique_ptr<int> p = make_unique<int>(42); 
    // Going out of scope... 
} 
// I did not leak my integer here! The destructor of unique_ptr called delete 

Jetzt unique_ptr ein Smart-Pointer ist, dass Modelle einzigartige Eigentum, was bedeutet, dass es jederzeit in Ihrem Programm sein soll - das ist, warum unique_ptr ist nicht kopierbar.

Solange Sie Smart Pointer in einer Weise verwenden, die den impliziten Vertrag nicht bricht, den Sie einhalten müssen, haben Sie die Garantie, dass kein Speicher verloren geht und die Eigentumsrichtlinien für Ihr Objekt korrekt sind erzwungen. Raw-Zeiger geben Ihnen diese Garantie nicht.

+2

Hallo, ich konnte nichts über 'Modellobjektbesitz ', das' Integerleck 'im Code oder' Durchsetzung von Besitzrichtlinien für Objekte 'verstehen. Könnten Sie bitte Themen/Ressourcen vorschlagen, um diese Konzepte zu lernen? –

+0

Ich kann 'unique_ptr' nicht verwenden, ohne einen Fehler zu bekommen:' Der Text ">" ist unerwartet. Es kann sein, dass dieses Token als Template-Argument-List-Terminator gedacht war, aber der Name ist nicht als Template bekannt.', obwohl ich '#include ' und '#include ' habe. Irgendein Rat? – Anonymous

2

Es gibt keinen Unterschied in beiden Konzepten der Zuweisung zu unique_ptr.

int* intPtr = new int(3); 
unique_ptr<int> uptr (intPtr); 

ist ähnlich

unique_ptr<int> uptr (new int(3)); 


how pointers, declared in this way will be different from the pointers declared in a "normal" way.

Wenn Sie eine ganze Zahl im Heap-Speicher (mit neuen Stichwort oder malloc) erstellen, dann müssen Sie löschen Sie diesen Speicher selbst (mit löschen oder frei jeweils).

Im folgenden Code,

int* heapInt = new int(5);//initialize int in heap memory 
. 
.//use heapInt 
. 
delete heapInt; 

Hier haben Sie zu heapInt löschen, wenn Sie es getan. Wenn es nicht gelöscht wird, tritt ein Speicherleck auf.
Um solche Speicherlecks zu vermeiden, wird unique_ptr verwendet, wobei unique_ptr automatisch den von heapInt belegten Speicherplatz löscht, wenn dieser den Gültigkeitsbereich verlässt.

Verwandte Themen