Question

  

Possible en double:    Comment libérer le pointeur de boost :: shared_ptr

Une fonction de mon interface renvoie un pointeur sur un objet. L'utilisateur est censé prendre possession de cet objet. Je ne veux pas retourner un Boost.shared_ptr, parce que je ne veux pas forcer les clients à utiliser boost. En interne cependant, je voudrais stocker le pointeur dans un shared_ptr pour éviter les fuites de mémoire en cas d'exceptions, etc. Il semble y avoir aucun moyen de détacher un pointeur d'un pointeur partagé. Toutes les idées ici?

Était-ce utile?

La solution

Qu'est-ce que vous cherchez est une fonction release; shared_ptr ne dispose pas d'une fonction de libération. par le manuel Boost :

  

Q. Pourquoi ne pas shared_ptr fournir une fonction release ()?

     

A. shared_ptr ne peut pas donner la propriété à moins qu'il est unique () parce que l'autre copie détruira encore l'objet.

     

Considérez:

shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2

int * p = a.release();

// Who owns p now? b will still call delete on it in its destructor.
  

En outre, le pointeur retourné par la libération () serait difficile à désaffecter de manière fiable, comme shared_ptr source aurait pu être créé avec un destructeur personnalisé.

Deux options que vous pourriez envisager:

  • Vous pouvez utiliser std::tr1::shared_ptr, ce qui nécessiterait vos utilisateurs d'utiliser une implémentation C ++ bibliothèque de soutien TR1 ou à utiliser Boost; au moins cela leur donnerait la possibilité de choisir entre les deux.
  • Vous pouvez implémenter votre propre pointeur partagé comme boost::shared_ptr et l'utiliser sur vos interfaces externes.

Vous pouvez regarder aussi à la discussion à cette question sur utilisant boost :: shared_ptr interface publique d'une bibliothèque .

Autres conseils

il y a toujours un moyen: -)

Il y a en effet une raison pour laquelle ils ne fournissent pas une méthode release (), mais il est impossible de créer un. Faites votre propre Deleter. Quelque chose sur la ligne (ont pas réellement compilé le code, mais c'est la notion générale):

template <typename T>
class release_deleter{
public:
  release_deleter() : released_(new some_atomic_bool(false)){}
  void release() {released_->set(true);}
  void operator()(T* ptr){if(!released_->get()) delete ptr;}
private:
  shared_ptr<some_atomic_bool> released_;
}

..

shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());

..

release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr);
deleter->release();
some_type* released_ptr = ptr.get();
  

L'utilisateur est censé prendre possession de cet objet. Je ne veux pas retourner un Boost.shared_ptr,

shared_ptr EXPRIME partagé la propriété, et vous voulez que votre interface pour exprimer Transfert de la propriété. std::auto_ptr serait donc plus applicable ici.

  

En interne cependant, je voudrais stocker le pointeur dans un shared_ptr pour éviter les fuites de mémoire en cas d'exceptions

Encore une fois, shared_ptr peut ne pas être le meilleur outil pour ce travail. Pour éviter les fuites dans le cas des exceptions, scoped_ptr ou auto_ptr seraient mieux adaptés.

Utilisez un shared_ptr à un scoped_ptr à la ressource (shared_ptr<scoped_ptr<Resource>>). De cette façon, vous obtenez le comptage de référence de shared_ptr, qui détruira automatiquement la ressource si et seulement si elle est encore attaché à la scoped_ptr. Mais vous pouvez détacher le scoped_ptr lorsque vous êtes prêt à remettre de la propriété.

James a bien couvert vous ne pouvez pas détacher vraiment un pointeur partagé.

Avez-vous besoin de plusieurs propriétaires en interne, ou êtes-vous transférer la propriété de votre classe au client? Dans ce cas, un std::auto_ptr pourrait correspondre à la facture.

Si vous êtes inquiet au sujet de la sémantique surprenante std::auto_ptr, vous pourriez le tenir en interne par boost::scoped_ptr et détacher au point vous la main hors - laissant au client de supprimer manuellement ou stocker dans leur propre pointeur intelligent.

Si vous avez plusieurs propriétaires de votre côté, vous pouvez utiliser un compte intrusif. En interne, vous pouvez alors utiliser boost::intrusive__ptr, mais main du pointeur brut à l'interface. Le client peut alors soit travailler manuellement avec un nombre de référence, ou le stocker dans un boost::intrusive_ptr eux-mêmes (mais vous ne leur faites pas en dépendent)

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