Maison >développement back-end >Tutoriel C#.Net >C 11 nouvelles fonctionnalités pointeurs intelligents (shared_ptr/unique_ptr/weak_ptr)

C 11 nouvelles fonctionnalités pointeurs intelligents (shared_ptr/unique_ptr/weak_ptr)

高洛峰
高洛峰original
2017-01-23 14:00:532012parcourir

Utilisation de base de shared_ptr

shared_ptr utilise le comptage de références pour gérer l'objet pointé. Lorsqu'il y a un nouveau shared_ptr pointant vers le même objet (copie du shared_ptr, etc.), le décompte de références est incrémenté de 1. Lorsque shared_ptr sort de la portée, le nombre de références est décrémenté de 1. Lorsque le compteur de références atteint 0, la mémoire gérée est libérée.

L'avantage est que cela soulage les programmeurs de la pression de libérer manuellement de la mémoire. Dans le passé, afin de gérer les exceptions dans le programme, il était souvent nécessaire d'encapsuler manuellement le pointeur dans une classe et de libérer la mémoire allouée dynamiquement via le destructeur ; désormais, ce processus peut être laissé à shared_ptr.

Généralement, nous utilisons make_shared pour obtenir shared_ptr.

cout<<"test shared_ptr base usage:"<<endl;
shared_ptr<string> p1 = make_shared<string>("");
if(p1 && p1->empty())
*p1 = "hello";
 
auto p2 = make_shared<string>("world");
cout<<*p1<<&#39; &#39;<<*p2<<endl;
 
cout<<"test shared_ptr use_count:"<<endl;
cout<<"p1 cnt:"<<p1.use_count()<<"\tp2 cnt:"<<p2.use_count()<<endl;
 
auto p3 = p2;
cout<<"p1 cnt:"<<p1.use_count()<<"\tp2 cnt:"<<p2.use_count()<<"\tp3 cnt:"<<p3.use_count()<<endl;
p2 = p1;
cout<<"p1 cnt:"<<p1.use_count()<<"\tp2 cnt:"<<p2.use_count()<<"\tp3 cnt:"<<p3.use_count()<<endl;

shared_ptr et new

shared_ptr peuvent être initialisés à l'aide d'un pointeur renvoyé par une nouvelle expression.

cout<<"test shared_ptr and new:"<<endl;
shared_ptr<int> p4(new int(1024));
//shared_ptr<int> p5 = new int(1024); // wrong, no implicit constructor
cout<<*p4<<endl;

Cependant, le pointeur renvoyé par une nouvelle expression ne peut pas être affecté à shared_ptr.

De plus, une attention particulière doit être portée à ne pas mélanger new et shared_ptr !

void process(shared_ptr<int> ptr)
{
cout<<"in process use_count:"<<ptr.use_count()<<endl;
}
 
cout<<"don&#39;t mix shared_ptr and normal pointer:"<<endl;
shared_ptr<int> p5(new int(1024));
process(p5);
int v5 = *p5;
cout<<"v5: "<<v5<<endl;
 
int *p6 = new int(1024);
process(shared_ptr<int>(p6));
int v6 = *p6;
cout<<"v6: "<<v6<<endl;

Le fragment de programme ci-dessus affichera :

in process use_count:2
v5 : 1024
in process use_count:1
v6 : 0
Vous pouvez voir que lorsque le processus p6 est utilisé pour la deuxième fois, le décompte de référence de shared_ptr est 1, En quittant la portée du processus, la mémoire correspondante sera libérée et p6 deviendra un pointeur suspendu.

Donc, une fois le pointeur renvoyé par une nouvelle expression géré par shared_ptr, n'accédez pas à cette mémoire via des pointeurs ordinaires !

shared_ptr.reset

shared_ptr peut être réinitialisé pour pointer vers un autre objet via la méthode de réinitialisation, auquel moment le nombre de références de l'objet d'origine est réduit de un.

cout<<"test shared_ptr reset:"<<endl;
cout<<"p1 cnt:"<<p1.use_count()<<"\tp2 cnt:"<<p2.use_count()<<"\tp3 nt:"<<p3.use_count()<<endl;
p1.reset(new string("cpp11"));
cout<<"p1 cnt:"<<p1.use_count()<<"\tp2 cnt:"<<p2.use_count()<<"\tp3 cnt:"<<p3.use_count()<<endl;
shared_ptr deleter

Vous pouvez personnaliser une fonction de suppression à appeler lorsque shared_ptr libère l'objet.

void print_at_delete(int *p)
{
cout<<"deleting..."<<p<<&#39;\t&#39;<<*p<<endl;
delete p;
}
 
cout<<"test shared_ptr deleter:"<<endl;
int *p7 = new int(1024);
shared_ptr<int> p8(p7, print_at_delete);
p8 = make_shared<int>(1025);

unique_ptr Utilisation de base

unique_ptr est exclusif à l'objet pointé, comme son nom l'indique. Par conséquent, unique_ptr ne peut pas être copié, attribué, etc., mais le contrôle peut être transféré entre unique_ptr via la fonction release.

cout<<"test unique_ptr base usage:"<<endl;
unique_ptr<int> up1(new int(1024));
cout<<"up1: "<<*up1<<endl;
unique_ptr<int> up2(up1.release());
cout<<"up2: "<<*up2<<endl;
//unique_ptr<int> up3(up1); // wrong, unique_ptr can not copy
//up2 = up1; // wrong, unique_ptr can not copy
unique_ptr<int> up4(new int(1025));
up4.reset(up2.release());
cout<<"up4: "<<*up4<<endl;

unique_ptr comme paramètre et valeur de retour

Il existe deux cas particuliers pour les restrictions de copie ci-dessus, c'est-à-dire que unique_ptr peut être utilisé comme fonction La valeur de retour et les paramètres sont utilisés Bien qu'il existe une copie implicite pour le moment, ce n'est pas irréalisable.

unique_ptr<int> clone(int p)
{
return unique_ptr<int>(new int(p));
}
 
void process_unique_ptr(unique_ptr<int> up)
{
cout<<"process unique ptr: "<<*up<<endl;
}
 
cout<<"test unique_ptr parameter and return value:"<<endl;
auto up5 = clone(1024);
cout<<"up5: "<<*up5<<endl;
process_unique_ptr(move(up5));
//cout<<"up5 after process: "<<*up5<<endl; // would cause segmentfault

La fonction std::move ici sera discutée en détail plus tard ^_^

unique_ptr deleter

unique_ptr peut également définir un deleter. Contrairement à shared_ptr, il doit spécifier le type de deleter dans le paramètre du modèle. Heureusement, nous disposons du puissant outil decltype, sinon ce serait difficile à écrire.

cout<<"test unique_ptr deleter:"<<endl;
int *p9 = new int(1024);
unique_ptr<int, decltype(print_at_delete) *> up6(p9, print_at_delete);
unique_ptr<int> up7(new int(1025));
up6.reset(up7.release());

weak_ptr

weak_ptr est généralement utilisé en conjonction avec shared_ptr. Il peut pointer vers l'objet pointé par shared_ptr, mais cela n'augmente pas le nombre de références de l'objet. De cette façon, il est possible que l'objet pointé par low_ptr ait effectivement été libéré. Par conséquent, faible_ptr a une fonction de verrouillage qui tente de récupérer un shared_ptr pointant vers l'objet.

cout<<"test weak_ptr basic usage:"<<endl;
auto p10 = make_shared<int>(1024);
weak_ptr<int> wp1(p10);
cout<<"p10 use_count: "<<p10.use_count()<<endl;
//p10.reset(new int(1025)); // this will cause wp1.lock() return a false obj
shared_ptr<int> p11 = wp1.lock();
if(p11) cout<<"wp1: "<<*p11<<" use count: "<<p11.use_count()<<endl;

Résumé

shared_ptr utilise le comptage de références pour gérer l'objet pointé.
Shared_ptr peut être initialisé à l'aide d'un pointeur renvoyé par une nouvelle expression ; cependant, un pointeur renvoyé par une nouvelle expression ne peut pas être attribué à shared_ptr.
Une fois le pointeur renvoyé par une nouvelle expression géré par shared_ptr, n'accédez pas à cette mémoire via des pointeurs ordinaires.
shared_ptr peut être réinitialisé pour pointer vers un autre objet via la méthode de réinitialisation. À ce stade, le nombre de références de l'objet d'origine est décrémenté de un.
Vous pouvez personnaliser une fonction de suppression à appeler lorsque shared_ptr libère l'objet.
unique_ptr est exclusif à l'objet pointé.
Unique_ptr ne peut pas être copié, attribué, etc., mais le contrôle peut être transféré entre unique_ptr via la fonction release.
unique_ptr peut être utilisé comme valeur de retour et paramètre de la fonction.
unique_ptr peut également définir un suppresseur, et le type de suppresseur doit être spécifié dans les paramètres du modèle.
Weak_ptr est généralement utilisé en conjonction avec shared_ptr. Il peut pointer vers l'objet pointé par shared_ptr, mais cela n'augmente pas le nombre de références de l'objet.
Weak_ptr a une fonction de verrouillage qui tente de récupérer un shared_ptr pointant vers l'objet.

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de chacun. J'espère également que tout le monde soutiendra le site Web PHP chinois.

Pour plus d'articles liés aux nouvelles fonctionnalités de C 11, aux pointeurs intelligents (shared_ptr/unique_ptr/weak_ptr), veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn