unique_ptr - smart pointer c++11




Qu'est-ce qu'un pointeur intelligent et quand devrais-je en utiliser un? (10)

Qu'est-ce qu'un pointeur intelligent et quand devrais-je en utiliser un?


Je voudrais ajouter un point à la question ci-dessus, le pointeur intelligent std :: shared_ptr n'a pas d'opérateur d'indice et ne supporte pas l'arithmétique de ponter, nous pouvons utiliser get () pour obtenir un pointeur intégré.


La plupart des types de pointeurs intelligents gèrent l'élimination de l'objet pointeur vers vous. C'est très pratique car vous n'avez plus à penser à vous débarrasser des objets manuellement.

Les pointeurs intelligents les plus couramment utilisés sont std::tr1::shared_ptr (ou boost::shared_ptr ) et, plus rarement, std::auto_ptr . Je recommande l'utilisation régulière de shared_ptr .

shared_ptr est très polyvalent et traite une grande variété de scénarios de mise au rebut, y compris les cas où les objets doivent être «transmis aux limites de la DLL» (le cas courant de cauchemar si différentes libc sont utilisées entre le code et les DLL).


Les définitions fournies par Chris, Sergdev et Llyod sont correctes. Je préfère cependant une définition plus simple, juste pour simplifier ma vie: Un pointeur intelligent est simplement une classe qui surcharge les opérateurs -> et * . Ce qui signifie que votre objet ressemble sémantiquement à un pointeur mais que vous pouvez le faire de façon bien plus cool, y compris le comptage des références, la destruction automatique, etc. shared_ptr et auto_ptr suffisent dans la plupart des cas, mais viennent avec leurs propres petites idiosyncrasies.


Les réponses existantes sont bonnes mais ne couvrent pas ce qu'il faut faire lorsqu'un pointeur intelligent n'est pas la réponse (complète) au problème que vous essayez de résoudre.

Entre autres choses (bien expliqué dans d'autres réponses) l'utilisation d'un pointeur intelligent est une solution possible à Comment utilisons-nous une classe abstraite comme un type de retour de fonction? qui a été marqué comme un doublon de cette question. Cependant, la première question à se demander si vous êtes tenté de spécifier une classe de base abstraite (ou en fait toute) comme type de retour en C ++ est "que voulez-vous vraiment dire?". Il y a une bonne discussion (avec d'autres références) de la programmation orientée objet idiomatique en C ++ (et comment cela est différent des autres langages) dans la documentation de la bibliothèque de conteneur de pointeur d'accentuation . En résumé, en C ++, vous devez penser à la propriété. Quels pointeurs intelligents vous aident, mais ne sont pas la seule solution, ou toujours une solution complète (ils ne vous donnent pas de copie polymorphe) et ne sont pas toujours une solution que vous voulez exposer dans votre interface (et un retour de fonction sonne horrible beaucoup comme une interface). Il peut être suffisant de renvoyer une référence, par exemple. Mais dans tous ces cas (pointeur intelligent, conteneur de pointeur ou simplement renvoyer une référence), vous avez changé le retour d'une valeur en une forme de référence . Si vous avez réellement besoin d'une copie, vous devrez peut-être ajouter plus de "idiome" ou aller au-delà de la POO idiomatique (ou autre) en C ++ vers un polymorphisme plus générique en utilisant des bibliothèques comme Adobe Poly ou Boost.TypeErasure .


Un pointeur intelligent est comme un pointeur régulier (typé), comme "char *", sauf lorsque le pointeur lui-même est hors de portée, puis il est également supprimé. Vous pouvez l'utiliser comme un pointeur régulier, en utilisant "->", mais pas si vous avez besoin d'un pointeur réel vers les données. Pour cela, vous pouvez utiliser "& * ptr".

C'est utile pour:

  • Les objets qui doivent être attribués avec du nouveau, mais que vous souhaitez avoir la même durée de vie que quelque chose sur cette pile. Si l'objet est affecté à un pointeur intelligent, il sera supprimé lorsque le programme quittera cette fonction / bloc.

  • Les membres de données des classes, de sorte que lorsque l'objet est supprimé toutes les données possédées sont également supprimées, sans aucun code spécial dans le destructeur (vous devrez vous assurer que le destructeur est virtuel, ce qui est presque toujours une bonne chose à faire) .

Vous pouvez ne pas vouloir utiliser un pointeur intelligent lorsque:

  • ... le pointeur ne devrait pas réellement posséder les données ... c'est-à-dire, lorsque vous utilisez simplement les données, mais que vous voulez qu'il survive à la fonction dans laquelle vous vous référez.
  • ... le pointeur intelligent ne sera pas lui-même détruit à un moment donné. Vous ne voulez pas qu'il reste en mémoire qui ne soit jamais détruit (comme dans un objet qui est dynamiquement alloué mais qui ne sera pas explicitement supprimé).
  • ... deux pointeurs intelligents pourraient pointer vers les mêmes données. (Il y a, cependant, des pointeurs encore plus intelligents qui vont gérer ça ... ce qu'on appelle le comptage des références .)

Voir également:


Un pointeur intelligent est un objet qui agit comme un pointeur, mais qui permet également de contrôler la construction, la destruction, la copie, le déplacement et le déréférencement.

On peut mettre en œuvre son propre pointeur intelligent, mais de nombreuses bibliothèques fournissent également des implémentations de pointeurs intelligentes, chacune présentant des avantages et des inconvénients différents.

Par exemple, Boost fournit les implémentations de pointeurs intelligentes suivantes:

  • shared_ptr<T> est un pointeur vers T utilisant un nombre de références pour déterminer quand l'objet n'est plus nécessaire.
  • scoped_ptr<T> est un pointeur automatiquement supprimé lorsqu'il sort de la portée. Aucune affectation n'est possible.
  • intrusive_ptr<T> est un autre pointeur de comptage de référence. Il fournit de meilleures performances que shared_ptr , mais nécessite le type T pour fournir son propre mécanisme de comptage de références.
  • weak_ptr<T> est un pointeur faible, travaillant en conjonction avec shared_ptr pour éviter les références circulaires.
  • shared_array<T> est comme shared_ptr , mais pour les tableaux de T
  • scoped_array<T> est comme scoped_ptr , mais pour les tableaux de T

Ce sont juste une description linéaire de chacun et peuvent être utilisés selon le besoin, pour plus de détails et d'exemples on peut regarder la documentation de Boost.

En outre, la bibliothèque standard C ++ fournit trois pointeurs intelligents; std::unique_ptr pour une propriété unique, std::shared_ptr pour une propriété partagée et std::weak_ptr . std::auto_ptr existait en C ++ 03 mais est maintenant obsolète.


Un pointeur intelligent est une classe, un wrapper d'un pointeur normal. Contrairement aux pointeurs normaux, le cercle de vie du point intelligent est basé sur un nombre de références (combien de temps l'objet pointeur intelligent est affecté). Ainsi, chaque fois qu'un pointeur intelligent est affecté à un autre, le compte de référence interne plus plus. Et chaque fois que l'objet est hors de portée, le nombre de références moins moins.

Le pointeur automatique, bien que similaire, est totalement différent du pointeur intelligent. C'est une classe pratique qui libère la ressource chaque fois qu'un objet pointeur automatique est hors de portée variable. Dans une certaine mesure, il crée un pointeur (pour la mémoire allouée dynamiquement) qui fonctionne de manière similaire à une variable de pile (allouée statiquement au moment de la compilation).


Voici le lien pour des réponses similaires: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Un pointeur intelligent est un objet qui agit, ressemble et se sent comme un pointeur normal mais offre plus de fonctionnalités. En C ++, les pointeurs intelligents sont implémentés en tant que classes de modèle qui encapsulent un pointeur et remplacent les opérateurs pointeurs standard. Ils ont un certain nombre d'avantages par rapport aux pointeurs réguliers. Ils sont garantis être initialisés en tant que pointeurs NULL ou pointeurs vers un objet tas. Indirection via un pointeur null est vérifiée. Aucune suppression n'est jamais nécessaire. Les objets sont automatiquement libérés lorsque le dernier pointeur leur a disparu. Un problème important avec ces pointeurs intelligents est que, contrairement aux pointeurs réguliers, ils ne respectent pas l'héritage. Les pointeurs intelligents ne sont pas attrayants pour le code polymorphe. Ci-dessous est un exemple pour la mise en œuvre de pointeurs intelligents.

Exemple:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Cette classe implémente un pointeur intelligent vers un objet de type X. L'objet lui-même est situé sur le tas. Voici comment l'utiliser:

smart_pointer <employee> p= employee("Harris",1333);

Comme d'autres opérateurs surchargés, p se comportera comme un pointeur régulier,

cout<<*p;
p->raise_salary(0.5);

Le pointeur intelligent est un type de type pointeur avec quelques fonctionnalités supplémentaires, par exemple, la désallocation automatique de la mémoire, le comptage des références, etc.

Petite intro est disponible sur la page Smart Pointers - Quoi, pourquoi, quoi? .

Std std::auto_ptr (chapitre 20.4.5 de la norme C ++) est un type de pointeur intelligent simple, qui permet de libérer automatiquement la mémoire lorsqu'elle est hors de portée et qui est plus robuste que la simple utilisation du pointeur lorsque des exceptions sont lancées, bien que moins flexible.

Un autre type pratique est boost::shared_ptr qui implémente le comptage des références et libère automatiquement la mémoire quand il ne reste aucune référence à l'objet. Cela permet d'éviter les fuites de mémoire et est facile à utiliser pour implémenter RAII .

Le sujet est couvert en profondeur dans le livre "C ++ Templates: The Complete Guide" par David Vandevoorde, Nicolai M. Josuttis , chapitre Chapitre 20. Smart Pointers. Quelques sujets couverts:


http://en.wikipedia.org/wiki/Smart_pointer

En informatique, un pointeur intelligent est un type de données abstrait qui simule un pointeur tout en fournissant des fonctionnalités supplémentaires, telles que la récupération automatique de place ou la vérification des limites. Ces fonctionnalités supplémentaires sont destinées à réduire les bogues causés par la mauvaise utilisation des pointeurs tout en conservant l'efficacité. Les pointeurs intelligents gardent généralement trace des objets qui leur pointent dans le but de la gestion de la mémoire. L'utilisation abusive des pointeurs est une source majeure de bugs: l'allocation, l'allocation et le référencement constants qui doivent être effectués par un programme écrit à l'aide de pointeurs rendent très probable l'apparition de fuites de mémoire. Les pointeurs intelligents tentent d'empêcher les fuites de mémoire en désactivant automatiquement la ressource: lorsque le pointeur sur un objet (ou le dernier d'une série de pointeurs) est détruit, par exemple parce qu'il est hors de portée, l'objet pointé est également détruit.





c++-faq