Obtenir un boost ::shared_ptr pour cela
Question
J'utilise largement boost:shared_ptr
dans mon code.En fait, la plupart des objets alloués sur le tas sont détenus par un shared_ptr
.Malheureusement, cela signifie que je ne peux pas passer this
dans n'importe quelle fonction qui prend un shared_ptr
.Considérez ce code :
void bar(boost::shared_ptr<Foo> pFoo)
{
...
}
void Foo::someFunction()
{
bar(this);
}
Ici, nous avons deux problèmes.Premièrement, cela ne sera pas compilé car le constructeur T* pour shared_ptr
est explicite.Deuxièmement, si je le force à construire avec bar(boost::shared_ptr<Foo>(this))
J'aurai créé un deuxième pointeur partagé vers mon objet qui finira par conduire à une double suppression.
Cela m'amène à ma question :Existe-t-il un modèle standard pour obtenir une copie du pointeur partagé existant dont vous savez qu'il existe à l'intérieur d'une méthode sur l'un de ces objets ?L'utilisation de références intrusives compte-t-elle ma seule option ici ?
La solution
Vous pouvez dériver de activer_shared_from_this puis vous pouvez utiliser "shared_from_this()" au lieu de "this" pour générer un pointeur partagé vers votre propre objet.
Exemple dans le lien :
#include <boost/enable_shared_from_this.hpp>
class Y: public boost::enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr<Y> p(new Y);
shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
C'est une bonne idée lors de la génération de threads à partir d'une fonction membre de boost::bind à shared_from_this() au lieu de cela.Cela garantira que l’objet ne soit pas libéré.
Autres conseils
Utilisez simplement un pointeur brut pour votre paramètre de fonction au lieu de shared_ptr. L'objectif d'un pointeur intelligent est de contrôler la durée de vie de l'objet, mais celle-ci est déjà garantie par les règles de cadrage C ++: elle existera au moins aussi longtemps que la fin de votre fonction. Autrement dit, le code d'appel ne peut éventuellement supprimer l'objet avant le retour de votre fonction; donc la sécurité d'un " dumb " le pointeur est garanti tant que vous n'essayez pas de supprimer l'objet dans votre fonction.
La seule fois où vous avez besoin de passer un shared_ptr dans une fonction, c’est lorsque vous voulez transférer la propriété de l’objet à la fonction ou que la fonction copie le pointeur.
boost a une solution pour ce cas d'utilisation, consultez enable_shared_from_this
Faites-vous vraiment plus de copies partagées de pFoo inside bar? Si vous ne faites rien de fou à l'intérieur, faites ceci:
void bar(Foo &foo)
{
// ...
}
Avec C ++ 11 shared_ptr
et enable_shared_from_this
se trouvent maintenant dans la bibliothèque standard. Ce dernier est, comme son nom l'indique, exactement dans ce cas.
http://fr.cppreference.com/w/cpp/memory/shared_ptr
http://en.cppreference.com/w/cpp/memory/enable_shared_from_thom_this
Exemple basé sur celui des liens ci-dessus:
struct Good: std::enable_shared_from_this<Good>{
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
utiliser:
std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
La fonction qui accepte un pointeur souhaite appliquer l'un des deux comportements suivants:
- Propriétaire de l'objet transmis et supprimez-le lorsqu'il sort de la portée. Dans ce cas, vous pouvez simplement accepter X * et envelopper immédiatement un scoped_ptr autour de cet objet (dans le corps de la fonction). Cela fonctionnera pour accepter & Quot; this & Quot; ou, en général, tout objet alloué par tas.
- Partagez un pointeur (ne le possédez pas) avec l'objet transmis. Dans ce cas, vous ne souhaitez pas utiliser du tout un scoped_ptr, car ne veut pas supprimer l'objet à la fin de votre fonction. Dans ce cas, ce que vous voulez théoriquement, c'est un shared_ptr (je l'ai déjà vu appelé linked_ptr ailleurs). La bibliothèque boost a une version de shared_ptr , et cela est également recommandé dans le livre Effective C ++ de Scott Meyers (élément 18 de la 3ème édition).
Modifier: Oups, j'ai légèrement mal interprété la question et je vois maintenant que cette réponse ne répond pas exactement à la question. De toute façon, je vais en rester là, au cas où cela pourrait être utile à quiconque travaille avec un code similaire.