Avec C ++ 17 , shared_ptr
peut être utilisé pour gérer un tableau alloué dynamiquement. L' shared_ptr
argument 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 T
est un type de tableau, ou delete p
, quand T
n'est pas un type de tableau, doit avoir un comportement bien défini et ne doit pas lever d'exceptions.
...
Remarques: Quand T
est un type tableau, ce constructeur ne doit pas participer à la résolution de surcharge à moins que l'expression delete[] p
est bien formée et soit T
est U[N]
et Y(*)[N]
est convertible T*
, ou T
est
U[]
et Y(*)[]
est convertible T*
. ...
Pour prendre en charge cela, le type de membre element_type
est 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 T
est U[N]
, i < N
. ...
Remarques: Quand T
n'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_ptr
ne pouvait pas être utilisé pour gérer des tableaux alloués dynamiquement. Par défaut, shared_ptr
appellera delete
l'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 delete
libérer la ressource.
Afin de l'utiliser correctement shared_ptr
avec 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_ptr
sera correctement appelé delete[]
lors de la destruction de l'objet géré.
Le suppresseur personnalisé ci-dessus peut être remplacé par
la std::default_delete
spé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_ptr
est 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_ptr
pour lui permettre de fonctionner immédiatement dans les cas où elle possède un tableau d'objets. Le projet actuel des shared_ptr
modifications prévues pour ce TS se trouve dans N4082 . Ces changements seront accessibles via l' std::experimental
espace de noms, et inclus dans l'en- <experimental/memory>
tête. Quelques-uns des changements pertinents pour la prise en charge shared_ptr
des tableaux sont:
- La définition du type de membre element_type
change
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_ptr
spé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 : Y
doit être un type complet. L'expression delete[] p
, quand T
est un type de tableau, ou delete p
, quand T
n'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 T
est U[N]
, Y(*)[N]
doit être convertible en T*
; quand T
est 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.