Avec C ++ 17 , shared_ptrpeut être utilisé pour gérer un tableau alloué dynamiquement. L' shared_ptrargument de modèle dans ce cas doit être T[N]ou T[]. Alors tu peux écrire
shared_ptr<int[]> sp(new int[10]);
À partir de n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requiert: Y doit être un type complet. L'expression delete[] p, quand Test un type de tableau, ou delete p, quand Tn'est pas un type de tableau, doit avoir un comportement bien défini et ne doit pas lever d'exceptions.
...
Remarques: Quand Test un type tableau, ce constructeur ne doit pas participer à la résolution de surcharge à moins que l'expression delete[] pest bien formée et soit Test U[N]et Y(*)[N]est convertible T*, ou Test
U[]et Y(*)[]est convertible T*. ...
Pour prendre en charge cela, le type de membre element_typeest désormais défini comme
using element_type = remove_extent_t<T>;
Les éléments du tableau peuvent être accédés en utilisant operator[]
element_type& operator[](ptrdiff_t i) const;
Nécessite: get() != 0 && i >= 0 . Si Test U[N], i < N. ...
Remarques: Quand Tn'est pas un type de tableau, il n'est pas spécifié si cette fonction membre est déclarée. Si elle est déclarée, son type de retour n'est pas spécifié, sauf que la déclaration (mais pas nécessairement la définition) de la fonction doit être bien formée.
Avant C ++ 17 , shared_ptrne pouvait pas être utilisé pour gérer des tableaux alloués dynamiquement. Par défaut, shared_ptrappellera deletel'objet géré lorsqu'il ne lui restera plus aucune référence. Cependant, lorsque vous attribuez une utilisation, new[]vous devez appeler delete[]et non deletelibérer la ressource.
Afin de l'utiliser correctement shared_ptravec un tableau, vous devez fournir un suppresseur personnalisé.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Créez le shared_ptr comme suit:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Maintenant shared_ptrsera correctement appelé delete[]lors de la destruction de l'objet géré.
Le suppresseur personnalisé ci-dessus peut être remplacé par
la std::default_deletespécialisation partielle des types de tableaux
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
une expression lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
De plus, à moins que vous n'ayez réellement besoin d'un partage de l'objet géré, a unique_ptrest mieux adapté pour cette tâche, car il a une spécialisation partielle pour les types de tableaux.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Modifications introduites par les extensions C ++ pour les principes de base de la bibliothèque
Une autre alternative pré-C ++ 17 à celles répertoriées ci-dessus a été fournie par la spécification technique de Library Fundamentals , qui a été augmentée shared_ptrpour lui permettre de fonctionner immédiatement dans les cas où elle possède un tableau d'objets. Le projet actuel des shared_ptrmodifications prévues pour ce TS se trouve dans N4082 . Ces changements seront accessibles via l' std::experimentalespace de noms, et inclus dans l'en- <experimental/memory>tête. Quelques-uns des changements pertinents pour la prise en charge shared_ptrdes tableaux sont:
- La définition du type de membre element_typechange
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Un membre operator[]est ajouté
element_type& operator[](ptrdiff_t i) const noexcept;
- Contrairement à la unique_ptrspécialisation partielle pour les tableaux, les deux shared_ptr<T[]>et shared_ptr<T[N]>seront valides et les deux aboutiront à delete[]être appelés sur le tableau d'objets géré.
template<class Y> explicit shared_ptr(Y* p);
Requiert : Ydoit être un type complet. L'expression delete[] p, quand Test un type de tableau, ou delete p, quand Tn'est pas un type de tableau, doit être bien formée, doit avoir un comportement bien défini et ne doit pas lever d'exceptions. Quand Test U[N], Y(*)[N]doit être convertible en T*; quand Test U[], Y(*)[]doit être convertible en T*; sinon, Y*sera convertible en T*.
std::vector. Vous devrez faire attention à passer le tableau en utilisant des références afin de ne pas en faire des copies. La syntaxe pour accéder aux données est plus propre que shared_ptr, et son redimensionnement est très très simple. Et vous obtenez tous les bienfaits de la STL si vous le souhaitez.