J'essaie de comprendre comment std::unique_ptr
fonctionne et pour cela j'ai trouvé ce document. L'auteur part de l'exemple suivant:
#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();
Ce qui est déroutant pour moi, c'est que dans cette ligne
unique_ptr<int> uptr (new int(3));
Nous utilisons un entier comme argument (entre parenthèses) et ici
unique_ptr<double> uptr2 (pd);
nous avons utilisé un pointeur comme argument. Cela fait-il une différence?
Ce qui n'est pas non plus clair pour moi, c'est en quoi les pointeurs, déclarés de cette manière, seront différents des pointeurs déclarés de manière "normale".
c++
pointers
std
unique-ptr
romain
la source
la source
new int(3)
renvoie un pointeur vers le nouveauint
, tout comme l'pd
était un pointeur vers le nouveaudouble
.Réponses:
Le constructeur de
unique_ptr<T>
accepte un pointeur brut vers un objet de typeT
(donc, il accepte aT*
).Dans le premier exemple:
Le pointeur est le résultat d'une
new
expression, tandis que dans le deuxième exemple:Le pointeur est stocké dans la
pd
variable.Conceptuellement, rien ne change (vous construisez un à
unique_ptr
partir d'un pointeur brut), mais la deuxième approche est potentiellement plus dangereuse, car elle vous permettrait, par exemple, de faire:Ainsi avoir deux pointeurs uniques qui encapsulent efficacement le même objet (violant ainsi la sémantique d'un pointeur unique ).
C'est pourquoi le premier formulaire de création d'un pointeur unique est préférable, lorsque cela est possible. Remarquez qu'en C ++ 14, nous pourrons faire:
Ce qui est à la fois plus clair et plus sûr. Maintenant concernant ce doute qui est le vôtre:
Les pointeurs intelligents sont censés modéliser la propriété de l'objet et se charger automatiquement de détruire l'objet pointé lorsque le dernier pointeur (intelligent, propriétaire) vers cet objet tombe hors de portée.
De cette façon , vous n'avez pas à vous rappeler de faire
delete
sur les objets attribués dynamiquement - le destructor du pointeur intelligent fera pour vous - ni à se soucier de savoir si vous ne serez pas déréférencer un (ballants) pointeur vers un objet qui a été détruit déjà:Il
unique_ptr
s'agit maintenant d' un pointeur intelligent qui modélise la propriété unique, ce qui signifie qu'à tout moment dans votre programme, il ne doit y avoir qu'un seul pointeur (propriétaire) vers l'objet pointé - c'est pourquoi ilunique_ptr
n'est pas copiable.Tant que vous utilisez des pointeurs intelligents d'une manière qui ne rompt pas le contrat implicite qu'ils vous demandent de respecter, vous aurez la garantie qu'aucune mémoire ne sera divulguée et que la politique de propriété appropriée pour votre objet sera appliquée. Les pointeurs bruts ne vous donnent pas cette garantie.
la source
model object ownership
, leinteger leak
dans le code ouenforcing ownership policy for object
. Pourriez-vous s'il vous plaît suggérer des sujets / ressources pour apprendre ces concepts?unique_ptr
, sans obtenir une erreur:,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.
même si j'ai#include <utility>
et#include <memory>
. Aucun conseil?Il n'y a aucune différence de travail dans les deux concepts d'affectation à unique_ptr.
est similaire à
Ici, unique_ptr supprime automatiquement l'espace occupé par
uptr
.Si vous créez un entier dans l'espace de tas (en utilisant un nouveau mot-clé ou malloc ), vous devrez effacer cette mémoire vous-même (en utilisant respectivement delete ou free ).
Dans le code ci-dessous,
Ici, vous devrez supprimer heapInt, lorsque vous aurez fini d'utiliser. S'il n'est pas supprimé, une fuite de mémoire se produit.
Afin d'éviter de telles fuites de mémoire, unique_ptr est utilisé, où unique_ptr supprime automatiquement l'espace occupé par heapInt lorsqu'il est hors de portée. Donc, vous n'avez pas besoin de supprimer ou de libérer pour unique_ptr.
la source
Les pointeurs uniques sont garantis pour détruire l'objet qu'ils gèrent lorsqu'ils sont hors de portée. http://en.cppreference.com/w/cpp/memory/unique_ptr
Dans ce cas:
pd
sera détruit lorsqu'iluptr2
sort du champ d'application. Cela facilite la gestion de la mémoire par suppression automatique.Le cas de
unique_ptr<int> uptr (new int(3));
n'est pas différent, sauf que le pointeur brut n'est affecté à aucune variable ici.la source
De cppreference , l'un des
std::unique_ptr
constructeurs estexplicite unique_ptr (pointeur p) noexcept;
Donc, créer un nouveau,
std::unique_ptr
c'est passer un pointeur vers son constructeur.Ou c'est la même chose que
La différence est que vous n'avez pas à nettoyer après l'avoir utilisé. Si vous n'utilisez pas
std::unique_ptr
(pointeur intelligent), vous devrez le supprimer comme cecilorsque vous n'en avez plus besoin ou cela provoquera une fuite de mémoire.
la source