Différences entre unique_ptr et shared_ptr

Dupliqués possibles:
pimpl: shared_ptr ou unique_ptr
les pointeurs intelligents (boost) expliqués

Quelqu’un pourrait-il expliquer les différences entre shared_ptr et unique_ptr?

Ces deux classes sont des pointeurs intelligents, ce qui signifie que, automatiquement (dans la plupart des cas), ils désalloueront l’object sur lequel ils pointent lorsque cet object ne peut plus être référencé. La différence entre les deux est de savoir combien de pointeurs différents de chaque type peuvent se référer à une ressource.

Lorsque vous utilisez unique_ptr , il ne peut y avoir au plus un unique_ptr pointant vers une ressource quelconque. Lorsque cet unique_ptr est détruit, la ressource est automatiquement récupérée. Comme il ne peut y avoir qu’un unique_ptr à une ressource, toute tentative de copie d’un unique_ptr entraînera une erreur de compilation. Par exemple, ce code est illégal:

 unique_ptr myPtr(new T); // Okay unique_ptr myOtherPtr = myPtr; // Error: Can't copy unique_ptr 

Cependant, unique_ptr peut être déplacé en utilisant la nouvelle sémantique de déplacement:

 unique_ptr myPtr(new T); // Okay unique_ptr myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr 

De même, vous pouvez faire quelque chose comme ceci:

 unique_ptr MyFunction() { unique_ptr myPtr(/* ... */); /* ... */ return myPtr; } 

Cet idiome signifie “Je vous retourne une ressource gérée. Si vous ne capturez pas explicitement la valeur de retour, la ressource sera nettoyée. Si vous le faites, vous avez désormais la propriété exclusive de cette ressource.” De cette façon, vous pouvez considérer unique_ptr comme un remplacement plus sûr et plus sûr de auto_ptr .

shared_ptr , d’autre part, permet à plusieurs pointeurs de pointer sur une ressource donnée. Lorsque le tout dernier shared_ptr vers une ressource est détruit, la ressource sera libérée. Par exemple, ce code est parfaitement légal:

 shared_ptr myPtr(new T); // Okay shared_ptr myOtherPtr = myPtr; // Sure! Now have two pointers to the resource. 

En interne, shared_ptr utilise le comptage de références pour suivre le nombre de pointeurs faisant référence à une ressource. Vous devez donc veiller à ne pas introduire de cycles de référence.

En bref:

  1. Utilisez unique_ptr lorsque vous voulez un seul pointeur vers un object qui sera récupéré lorsque ce seul pointeur est détruit.
  2. Utilisez shared_ptr lorsque vous souhaitez plusieurs pointeurs sur la même ressource.

J’espère que cela t’aides!

unique_ptr est le pointeur intelligent de choix si vous avez juste un object dynamic quelque part pour lequel un consommateur a une responsabilité unique (donc “unique”) – peut-être une classe de wrapper qui doit conserver des objects dynamicment alloués. unique_ptr a très peu de frais généraux. Ce n’est pas copiable, mais mobile. Son type est template class unique_ptr; , cela dépend donc de deux parameters de modèle.

unique_ptr est aussi ce que auto_ptr voulait être dans l’ancien C ++ mais ne pouvait pas en raison des limitations de ce langage.

shared_ptr est un animal très différent. La différence évidente est que de nombreux consommateurs peuvent partager la responsabilité d’un object dynamic (donc «partagé»), et l’object ne sera détruit que lorsque tous les pointeurs partagés auront disparu. De plus, vous pouvez avoir des indicateurs faibles qui seront intelligemment informés si le pointeur partagé qu’ils ont suivi a disparu.

En interne, shared_ptr a beaucoup plus à faire: il y a un compte de référence, qui est mis à jour de manière atomique pour permettre l’utilisation dans le code concurrent. En outre, il y a beaucoup d’allocation en cours, une pour un “bloc de contrôle de référence” de comptabilité interne et une autre (souvent) pour l’object membre réel.

Mais il y a une autre grande différence: le type de pointeur partagé est toujours template class shared_ptr; , et cela malgré le fait que vous pouvez l’initialiser avec des parameters personnalisés et avec des allocateurs personnalisés. Le programme de suppression et d’allocation sont suivis à l’aide de l’effacement de type et de la répartition des fonctions virtuelles, ce qui ajoute au poids interne de la classe. Les avantages des différents types de pointeurs partagés de type T sont différents. Ainsi, ils expriment vraiment le concept de «responsabilité partagée pour T » sans alourdir le consommateur!

shared_ptr et unique_ptr sont conçus pour être passés par valeur (avec l’exigence de mobilité évidente pour le pointeur unique). Vous ne devriez pas non plus vous inquiéter de la surcharge, car leur puissance est vraiment étonnante, mais si vous avez le choix, préférez unique_ptr , et utilisez uniquement shared_ptr si vous avez vraiment besoin de responsabilités partagées.

unique_ptr
est un pointeur intelligent qui possède un object exclusivement.

shared_ptr
est un pointeur intelligent pour la propriété partagée. Il est à la fois copyable et movable . Plusieurs instances de pointeur intelligent peuvent posséder la même ressource. Dès que le dernier pointeur intelligent possédant la ressource est hors de scope, la ressource sera libérée.

Lorsque vous encapsulez un pointeur dans un unique_ptr vous ne pouvez pas avoir plusieurs copies de unique_ptr . Le shared_ptr contient un compteur de référence qui compte le nombre de copies du pointeur stocké. Chaque fois qu’un shared_ptr est copié, ce compteur est incrémenté. Chaque fois qu’un shared_ptr est détruit, ce compteur est décrémenté. Lorsque ce compteur atteint 0, l’object stocké est détruit.