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
?
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
.
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
.
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.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.
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.
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.