web-dev-qa-db-fra.com

Pourquoi est-il faux d'utiliser std :: auto_ptr <> avec des conteneurs standard?

Pourquoi est-il faux d'utiliser std::auto_ptr<> avec des conteneurs standard?

205
Uhall

La norme C++ dit qu'un élément STL doit être "copiable" et "assignable". En d'autres termes, un élément doit pouvoir être affecté ou copié et les deux éléments sont logiquement indépendants. std::auto_ptr ne remplit pas cette condition.

Prenons par exemple ce code:

class X
{
};

std::vector<std::auto_ptr<X> > vecX;
vecX.Push_back(new X);

std::auto_ptr<X> pX = vecX[0];  // vecX[0] is assigned NULL.

Pour surmonter cette limitation, vous devez utiliser le std::unique_ptr , std::shared_ptr ou std::weak_ptr pointeurs intelligents ou équivalents boost si vous n’avez pas C++ 11. Voici la documentation de la bibliothèque boost pour ces pointeurs intelligents.

123
Kevin

La sémantique de la copie de auto_ptr ne sont pas compatibles avec les conteneurs.

Plus précisément, copier un auto_ptr à un autre ne crée pas deux objets égaux car l’un a perdu la propriété du pointeur.

Plus spécifiquement, copier un auto_ptr laisse l'une des copies lâcher le pointeur. Lequel de ces restes dans le conteneur n'est pas défini. Par conséquent, vous pouvez perdre au hasard l'accès aux pointeurs si vous stockez auto_ptrs dans les conteneurs.

65
Frank Krueger
38
Lazer

Les conteneurs STL doivent pouvoir copier les éléments que vous y stockez et sont conçus pour s'attendre à ce que l'original et la copie soient équivalents. Les objets pointeur automatique ont un contrat complètement différent, dans lequel la copie crée un transfert de propriété. Cela signifie que les conteneurs de auto_ptr présenteront un comportement étrange, en fonction de l'utilisation.

Il existe une description détaillée de ce qui peut aller de mal dans le point 8 de Effective STL (Scott Meyers), ainsi qu'une description peu détaillée dans le point 13 de Effective C++ (Scott Meyers).

17
Garth Gilmour

Les conteneurs STL stockent des copies des éléments contenus. Lorsqu’un auto_ptr est copié, l’ancien ptr est défini sur null. De nombreuses méthodes de conteneur sont rompues par ce comportement.

12
Dustin Getz

La norme C++ 03 (ISO-CEI 14882-2003) stipule dans la clause 20.4.5, paragraphe 3:

[...] [Remarque: [...] auto_ptr ne répond pas aux exigences CopyConstructible et Assignable pour les éléments de conteneur Standard Library. Par conséquent, l'instanciation d'un conteneur Standard Library avec un auto_ptr entraîne un comportement indéfini. - note de fin]

La norme C++ 11 (ISO-CEI 14882-2011) stipule à l’annexe D.10.1, paragraphe 3:

[...] Remarque: [...] les instances de auto_ptr répondent aux exigences de MoveConstructible et MoveAssignable, mais ne répondent pas aux exigences de CopyConstructible et CopyAssignable. - end note]

La norme C++ 14 (ISO-CEI 14882-2014) indique à l'annexe C.4.2 de l'annexe D: caractéristiques de compatibilité:

Change : modèles de classe auto_ptr, unary_function et binary_function, modèles de fonction random_shuffle et modèles de fonction (et leurs types de retour) ptr_fun , mem_fun, mem_fun_ref, bind1st et bind2nd ne sont pas définis.
Justification : remplacé par de nouvelles fonctionnalités.
Effet sur la fonctionnalité d'origine : Le code C++ 2014 valide qui utilise ces modèles de classe et ces modèles de fonction peut ne pas être compilé dans la présente Norme internationale .

4
bitek