web-dev-qa-db-fra.com

std :: auto_ptr à std :: unique_ptr

Avec la nouvelle norme à venir (et des parties déjà disponibles dans certains compilateurs), le nouveau type std::unique_ptr est supposé remplacer std::auto_ptr.

Leur utilisation se chevauche-t-elle exactement (pour que je puisse effectuer une recherche/un remplacement global sur mon code (ce n'est pas ce que je ferais, mais si je le faisais)) ou devrais-je être conscient de certaines différences qui n'apparaissent pas à la lecture de la documentation?

De plus, s'il s'agit d'un remplacement direct, pourquoi lui attribuer un nouveau nom plutôt que simplement améliorer le std::auto_ptr?

180
Martin York

Vous ne pouvez pas effectuer une recherche/remplacement globale car vous pouvez copier un fichier auto_ptr (avec conséquences connues), mais un unique_ptr ne peut être déplacé. Tout ce qui ressemble à

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

devra devenir au moins comme ça

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

En ce qui concerne les autres différences, unique_ptr peut gérer les tableaux correctement (il appellera delete[], tandis que auto_ptr tentera d'appeler delete.

211
Cubbi

std::auto_ptr et std::unique_ptr sont incompatibles entre eux et remplaçants dans d'autres. Donc, trouver/remplacer n'est pas assez bon. Cependant, après une recherche/remplacement, les erreurs de compilation doivent être corrigées, à l'exception des cas étranges. La plupart des erreurs de compilation nécessiteront l'ajout d'un std::move.

  • Variable de la fonction:
    100% compatible, tant que vous ne le transmettez pas en valeur à une autre fonction.
  • Type de retour:
    pas compatible à 100% mais compatible à 99% ne semble pas faux.
  • paramètre de fonction par valeur:
    100% compatible avec une mise en garde, unique_ptr s doit être transmis via un appel std::move. Celui-ci est simple car le compilateur se plaindra si vous ne le faites pas correctement.
  • paramètre de fonction par référence:
    100% compatible.
  • Variable membre de classe:
    Celui-ci est délicat. La sémantique de copie de std::auto_ptr est diabolique. Si la classe n'autorise pas la copie, alors std::unique_ptr est un remplacement instantané. Cependant, si vous essayez de donner à la classe une sémantique de copie raisonnable, vous devrez modifier le code de traitement std::auto_ptr. Ceci est simple car le compilateur se plaindra si vous ne le faites pas correctement. Si vous autorisez la copie d'une classe avec un std::auto_ptr membre sans aucun code spécial, honte à vous et bonne chance.

En résumé, std::unique_ptr est un std::auto_ptr ininterrompu. Il interdit les comportements lors de la compilation qui étaient souvent erreurs lors de l'utilisation de std::auto_ptr. Donc, si vous avez utilisé std::auto_ptr avec tout le soin dont vous avez besoin, passer à std::unique_ptr devrait être simple. Si vous vous êtes fié au comportement étrange de std::auto_ptr, vous devez de toute façon refactoriser votre code.

88
deft_code

AUTANT QUE JE SACHE, unique_ptr n'est pas un remplacement direct. Le défaut majeur qu’il corrige est le transfert implicite de propriété.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

D'autre part, unique_ptr aura de nouvelles capacités: elles peuvent être stockées dans des conteneurs.

33
UncleBens

Herb Sutter a une bonne explication sur GotW # 89 :

Quel est le problème avec auto_ptr? auto_ptr est caractérisé de la manière la plus charitable comme une vaillante tentative de création d’un unique_ptr avant que C++ n’ait une sémantique de déplacement. auto_ptr est maintenant obsolète et ne devrait pas être utilisé dans le nouveau code.

Si vous avez auto_ptr dans une base de code existante, lorsque vous en avez l'occasion, essayez d'effectuer une recherche globale et de remplacer auto_ptr en unique_ptr; la grande majorité des utilisations fonctionneront de la même manière, et cela pourrait exposer (par une erreur de compilation) ou corriger (en silence) un bogue ou deux que vous ne saviez pas que vous aviez.

En d'autres termes, bien qu'une recherche et un remplacement globaux puissent "casser" temporairement votre code, vous devriez le faire quand même: il faudra un certain temps pour corriger les erreurs de compilation, mais cela vous évitera beaucoup plus de problèmes à long terme.

27
ValarDohaeris