web-dev-qa-db-fra.com

Créer un boost :: shared_ptr à une variable existante

J'ai une variable existante, par exemple.

int a = 3;

Comment puis-je maintenant créer un boost::shared_ptr à a? Par exemple:

boost::shared_ptr< int > a_ptr = &a; // this doesn't work
27
Bill Cheatham

même si vous devez placer la variable dans un pointeur géré lors de sa création pour le faire à partir d'un pointeur existant.

int *a=new int;
boost::shared_ptr<int> a_ptr(a);

Cela dit, vous ne voulez certainement pas placer des variables de pile dans shared_ptr

Si pour une raison quelconque une fonction prend shared_ptr et que vous n'avez qu'une pile disponible, vous feriez mieux de faire ceci:

int a=9;
boost::shared_ptr<int> a_ptr=boost::make_shared(a);

Vois ici:

http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/make_shared.html

il convient également de noter que shared_ptr est dans la norme c ++ 11 si vous pouvez l'utiliser. Vous pouvez utiliser auto en combinaison avec make_shared comme les notes de Herb Sutter dans le discours de construction.

#include <memory>

int a=9;
auto a_ptr=std::make_shared(9);
43
111111

Tout d'abord, vous avez une erreur car shared_ptr ne convertira pas automatiquement à partir d'un pointeur du type approprié. Vous devez déclarer explicitement que c'est ce que vous voulez faire:

int a = 3;
::boost::shared_ptr< int > a_ptr(&a); // DO NOT DO THIS!

Mais vous avez un autre problème. Imaginez l'effet de ce code:

int a = 3;
delete &a;

Dans le premier exemple que j'ai donné, cela se produira inévitablement, même si ce n'est pas aussi direct. shared_ptr La raison d'être de _ est de supprimer des choses quand tous les pointeurs vers elle disparaissent. Bien sûr, cela provoquera toutes sortes de comportements étranges.

Vous avez deux façons de traiter ce problème. L'une consiste à créer quelque chose qui peut être supprimé. L'autre consiste à s'assurer que shared_ptr ne supprime pas réellement la chose vers laquelle il pointe. Il y a des avantages et des inconvénients à chacun.

Faire quelque chose qui peut être supprimé:

Avantages:

  • Simple et facile.
  • Vous n'avez pas à vous soucier de la durée de vie des objets.

Les inconvénients:

  • Un peu lent, car cela impliquera une allocation de tas ou deux.
  • La résultante shared_ptr fera référence à une copie, donc les modifications apportées à a ne seront pas reflétées dans la valeur de l'élément vers lequel il pointe.

Comment faire:

::boost::shared_ptr<int> a_ptr(::boost::make_shared(a));

Ceci est assez similaire à (et cela fonctionnera également):

::boost::shared_ptr<int> a_ptr(new int(a));

Mais c'est un peu plus efficace. ::boost::make_shared fait de la magie pour allouer le nombre de références et l'objet dans la mémoire contiguë, ce qui économise les appels à l'allocateur et améliore la localité de référence.

Faire en sorte que shared_ptr ne supprime pas réellement ce qu'il pointe:

Avantages:

  • Plus rapide, bien qu'il implique toujours une allocation de tas pour le compte de référence
  • Résout directement le problème en cours (la chose que vous pointez ne peut pas être supprimée).
  • Le shared_ptr fait référence à a, donc si vous changez sa valeur, les choses qui y accèdent via le pointeur verront la nouvelle valeur.

Les inconvénients:

  • Nécessite d'en savoir un peu plus sur la façon dont shared_ptr fonctionne, ce qui signifie que les personnes qui lisent votre code doivent également le savoir.
  • Si la chose que vous pointez sort du cadre avant tout shared_ptr c'est ce que ça veut dire, alors ces pointeurs deviennent pendants, et c'est mauvais.
  • Le point précédent en fait un solution très risquée. Je l'éviterais généralement.

Comment faire:

Quelque part en dehors de la fonction (probablement dans un espace de noms anonyme):

void do_nothing_deleter(int *)
{
    return;
}

Et puis dans la fonction:

int a = 3;
::boost::shared_ptr a_ptr(&a, do_nothing_deleter);
32
Omnifarious

Ce que vous avez écrit ne fonctionnera pas car le constructeur de shared_ptr que vous recherchez est explicit, vous devez donc l'écrire comme ceci

boost::shared_ptr<int> a_ptr(&a); // Don't do that!

Le problème avec qui est cependant que delete sera appelé sur la valeur stockée de a_ptr. Puisque dans votre exemple, a a une durée de stockage automatique, c'est très mauvais. Nous passons donc également un suppresseur personnalisé:

boost::shared_ptr<int> a_ptr(&a, noop_deleter);

Une implémentation de noop_deleter pour C++ 11:

auto noop_deleter = [](int*) {};

Version C++ 03:

// Can't be put in local scope
struct {
    void
    operator()(int*) const
    {}
} noop_deleter;
15
Luc Danton

Vous ne pouvez pas créer un boost :: shared_ptr pour une variable existante. Les éléments stockés dans un boost :: shared_ptr sont stockés à la création.

Vous pouvez cependant faire un boost :: shared_ptr qui est une copie d'une variable existante.

Par exemple

int a = 3; // Existing variable
boost::shared_ptr<int> aCopy = boost::make_shared<int>(a); //Create copy with value of a

Notez que vous devrez inclure <boost/make_shared.hpp> pour make_shared.

8
Lalaland