Question

Nous avons plus ou moins utilisé boost :: shared_ptr dans l'ensemble de notre code, mais nous avons encore quelques cas isolés d'utilisation de std :: auto_ptr . , y compris les classes de singleton:

template < typename TYPE >
class SharedSingleton
{
public: 
    static TYPE& Instance()
    {
        if (_ptrInstance.get() == NULL)
            _ptrInstance.reset(new TYPE);
        return *_ptrInstance;
    }

protected: 
    SharedSingleton() {};

private:
    static std::auto_ptr < TYPE > _ptrInstance;
};

On m'a dit qu'il y avait une très bonne raison pour laquelle cela n'a pas été transformé en shared_ptr , mais pour la vie de moi, je ne comprends pas pourquoi? Je sais que auto_ptr finira par être marqué comme amorti dans le prochain standard. Je voudrais donc savoir ce que / comment je peux remplacer cette implémentation .

Par ailleurs, existe-t-il d'autres raisons pour lesquelles vous envisageriez d'utiliser un auto_ptr au lieu d'un shared_ptr ? et voyez-vous des problèmes passer à shared_ptr à l'avenir?

Modifier:

  1. En réponse à " puis-je remplacer en toute sécurité auto_ptr par shared_ptr dans le code ci-dessus, la réponse est oui, mais je vais prendre un petit coup en performance .
  2. Lorsque auto_ptr est finalement marqué comme amorti et que nous passons à std :: shared_ptr , nous devons tester minutieusement notre code pour nous assurer de notre intégrité. par la sémantique de propriété différente.
Était-ce utile?

La solution

auto_ptr et shared_ptr résolvent des problèmes totalement différents. L'un ne remplace pas l'autre.

auto_ptr est une fine couche de pointeurs permettant de mettre en œuvre la Sémantique RAII . , afin que les ressources soient toujours libérées, même face à des exceptions. auto_ptr n'effectue aucun comptage de références ou autre, il ne fait pas que plusieurs pointeurs pointent vers le même objet lors de la création de copies. En fait, c'est très différent. auto_ptr est l'une des rares classes dans lesquelles l'opérateur d'affectation modifie l'objet source . Considérez cette fiche sans vergogne de la page wikipedia auto_ptr :

int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;

y = x;

cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i

Notez comment l'exécution

y = x;

modifie non seulement y mais aussi x.

Le modèle boost :: shared_ptr facilite la gestion de plusieurs pointeurs sur le même objet. Cet objet n'est supprimé que lorsque la dernière référence à celui-ci est sortie de sa portée. Cette fonctionnalité n’est pas utile dans votre scénario qui implémente un Singleton . Dans votre scénario, il y a toujours soit 0 référence à 1 référence au seul objet de la classe, le cas échéant.

En substance, les objets auto_ptr et les objets shared_ptr ont une sémantique totalement différente (c'est pourquoi vous ne pouvez pas utiliser le premier dans des conteneurs, mais le faire avec le dernier convient très bien), et j'espère bien que vous aurez de bons tests pour détecter les régressions que vous avez introduites lors du portage de votre code. : -}

Autres conseils

D'autres ont répondu pourquoi ce code utilise un auto_ptr au lieu d'un code_partagé . Pour répondre à vos autres questions:

Quoi / comment je peux remplacer cette implémentation?

Utilisez boost :: scoped_ptr ou unique_ptr (disponible à la fois dans Boost et dans la nouvelle norme C ++). scoped_ptr et unique_ptr fournissent une propriété stricte (sans aucun temps de comptage de références) et évitent la sémantique surprenante de la suppression sur copie de auto_ptr .

En outre, y a-t-il d'autres raisons pour lesquelles vous envisagez d'utiliser un auto_ptr au lieu d'un shared_ptr ? Et voyez-vous des problèmes pour passer à shared_ptr à l'avenir?

Personnellement, je n’utiliserais pas de auto_ptr . Supprimer sur copie est tout simplement trop intuitif. Herb Sutter semble être d'accord . Passer à scoped_ptr , unique_ptr ou shared_ptr ne devrait poser aucun problème. Plus précisément, shared_ptr devrait remplacer immédiatement le client si vous ne vous souciez pas de la surcharge du comptage des références. scoped_ptr est un remplacement immédiat si vous n'utilisez pas les fonctionnalités de transfert de propriété de auto_ptr . Si vous utilisez le transfert de propriété, alors unique_ptr est presque un remplacement immédiat, sauf que vous devez appeler explicitement move pour transférer la propriété. Voir ici pour un exemple.

auto_ptr est le seul type de pointeur intelligent que j'utilise. Je l'utilise parce que je n'utilise pas Boost, et parce que je préfère généralement mes classes orientées métier / application à explicitement définir la sémantique et l'ordre de suppression, plutôt que de dépendre collections de pointeurs intelligents ou individuels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top