161 votes

shared_ptr pour un tableau : doit-il être utilisé?

Juste une petite question concernant shared_ptr.

Est-ce une bonne pratique d'utiliser shared_ptr pointant vers un tableau? e.g shared_ptr<int> sp(new int[10]);

Si non, quelqu'un peut-il me dire pourquoi? Une raison pour laquelle je suis déjà au courant est on ne peut incrémenter/décrémenter le shared_ptr. Par conséquent, il ne peut pas être utilisé comme un simple pointeur vers un tableau.

248voto

Praetorian Points 47122

Par défaut, shared_ptr appellerons delete sur l'objet géré lorsque toutes les références restent. Toutefois, lorsque vous allouer à l'aide de new[] vous devez appeler delete[], et pas delete, pour libérer la ressource.

Afin d'utiliser correctement l' shared_ptr avec un tableau, vous devez fournir une coutume deleter.

template< typename T >
struct array_deleter
{
  void operator ()( T const * p)
  { 
    delete[] p; 
  }
};

Créer le shared_ptr comme suit

std::shared_ptr<int> sp( new int[10], array_deleter<int>() );

Maintenant, shared_ptr correctement appelez delete[] lors de la destruction de l'objet géré.


Avec C++11, vous pouvez également utiliser une lambda au lieu de le foncteur.

std::shared_ptr<int> sp( new int[10], []( int *p ) { delete[] p; } );

Aussi, à moins que vous vraiment besoin de partager l'objet géré, unique_ptr est le mieux adapté pour cette tâche, car il a une spécialisation partielle pour les types de tableau.

std::unique_ptr<int[]> up( new int[10] ); // this will correctly call delete[]


Les changements introduits par les Extensions C++ pour la Bibliothèque Fondamentaux

shared_ptr est renforcé par la Bibliothèque Fondamentaux Spécification Technique (TS) pour lui permettre de travailler hors de la boîte pour le cas où il possède un tableau d'objets; il n'y aura pas besoin de les fournissez un deleter. Le projet actuel de l' shared_ptr changements prévus pour cet TS peut être trouvé dans N4082. Ces changements seront accessibles via l' std::experimental d'espace de noms, et inclus dans l' <experimental/memory> - tête. Quelques-uns des changements pertinents à l'appui de shared_ptr pour les tableaux sont:

— La définition du type de membre element_type changements

typedef T element_type;

 typedef typename remove_extent<T>::type element_type;

— Membre de l' operator[] est ajouté

 element_type& operator[](ptrdiff_t i) const noexcept;

— Contrairement à l' unique_ptr partielle de spécialisation pour les tableaux, les deux shared_ptr<T[]> et shared_ptr<T[N]> seront valables, et tous les deux vont entraîner delete[] d'être appelé sur la gestion de l'ensemble d'objets.

 template<class Y> explicit shared_ptr(Y* p);

Nécessite: Y doit être d'un type complètes. L'expression delete[] p, lorsque T est de type tableau, ou delete p, lorsque T n'est pas de type tableau, doit être bien formé, doit avoir bien défini le comportement, et ne doit pas jeter des exceptions. Lors de l' T est U[N], Y(*)[N] sont convertibles T*; lorsque l' T est U[], Y(*)[] sont convertibles T*; sinon, Y* doit être convertibles T*.

26voto

Timmmm Points 9909

Une alternative plus facile que vous pourriez être en mesure d'utiliser est - shared_ptr<vector<int>>.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X