Maison >développement back-end >Tutoriel C#.Net >C 11 nouvelles fonctionnalités pointeurs intelligents (shared_ptr/unique_ptr/weak_ptr)
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<<' '<<*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'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<<'\t'<<*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 !