Crear un ptr boost::shared a una variable existente


Tengo una variable existente, por ejemplo,

int a = 3;

¿Cómo puedo crear ahora un boost::shared_ptr a a? Por ejemplo:

boost::shared_ptr< int > a_ptr = &a; // this doesn't work
Author: Null, 2011-12-11

4 answers

Aunque debe poner la variable en un puntero administrado en su creación para hacerlo desde un puntero existente.

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

Dicho esto, definitivamente no quieres poner variables de pila en shared_ptr.]}

Si por alguna razón una función toma shared_ptr y solo tiene una pila varaible, es mejor hacer esto:

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

Véase aquí:

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

También vale la pena señalar que shared_ptr está en el estándar c++11 si puede usar eso. Puede usar auto en combinación con make_shared como Herb Sutter notes en la charla de compilación.

#include <memory>

int a=9;
auto a_ptr=std::make_shared(9);
 42
Author: 111111,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-11 19:00:20

Primero, tiene un error porque shared_ptr no se convertirá automáticamente desde un puntero del tipo apropiado. Tienes que declarar explícitamente que eso es lo que quieres hacer:

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

Pero tienes otro problema. Imagine el efecto de este código:

int a = 3;
delete &a;

En el primer ejemplo que di, esto sucederá inevitablemente, incluso si no es tan directo. shared_ptr's toda la razón de la existencia es borrar las cosas cuando todos los punteros a ella desaparecen. Esto, por supuesto, hará que todos un comportamiento extraño.

Usted tiene dos maneras de lidiar con este problema. Una es crear algo que pueda ser eliminado. La otra es asegurarse de que shared_ptr no elimine realmente la cosa a la que apunta. Hay pros y contras a cada uno.

Haciendo algo que se puede borrar:

Ventajas:

  • Simple y fácil.
  • No tienes que preocuparte por la vida de los objetos.

Contras:

  • Un poco lento lado, ya que implicará una asignación de montón o dos.
  • El shared_ptr resultante se referirá a una copia, por lo que las modificaciones a a no se reflejarán en el valor de la cosa a la que apunta.

Cómo hacerlo:

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

Esto es bastante similar a (y esto también funcionará):

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

Pero es un poco más eficiente. ::boost::make_shared hace algo de magia para asignar el recuento de referencias y el objeto en memoria contigua, lo que ahorra llamadas al asignador y mejora localidad de referencia.

Haciendo que shared_ptr no elimine realmente lo que apunta:

Ventajas:

  • Más rápido, aunque todavía implica una asignación de montón para el recuento de referencia
  • Aborda directamente el problema en cuestión (la cosa a la que estás apuntando no se puede eliminar).
  • El shared_ptr se refiere a a, por lo que si cambia su valor las cosas que acceden a él a través del puntero verán el nuevo valor.

Contras:

  • Requiere saber un poco más sobre cómo funciona shared_ptr, lo que significa que las personas que leen su código también deben saberlo.
  • Si la cosa a la que estás apuntando sale del alcance antes de que todos los shared_ptr que apuntan a ella lo hagan, entonces esos punteros se vuelven colgantes, y eso es malo.
  • El punto anterior lo convierte en una solución muy arriesgada. Generalmente lo evitaría.

Cómo hacerlo:

En algún lugar fuera de la función (probablemente en un espacio de nombres anónimo):

void do_nothing_deleter(int *)
{
    return;
}

Y luego en la función:

int a = 3;
::boost::shared_ptr a_ptr(&a, do_nothing_deleter);
 30
Author: Omnifarious,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-11 23:12:32

Lo que escribiste no funcionará porque el constructor de shared_ptr que estás buscando es explicit, por lo que tendrías que escribirlo así

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

El problema con que sin embargo, es que delete se llamará sobre el valor almacenado de a_ptr. Dado que en su ejemplo a tiene una duración de almacenamiento automática, esto es muy malo. Así que pasamos en un deleter personalizado también:

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

Una implementación de noop_deleter para C++11:

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

C++03 version:

// Can't be put in local scope
struct {
    void
    operator()(int*) const
    {}
} noop_deleter;
 13
Author: Luc Danton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-11 18:56:17

No se puede crear un boost::shared_ptr para una variable existente. Los elementos almacenados en un boost:: shared_ptr se almacenan en la creación.

Sin embargo, puede hacer un boost::shared_ptr que es una copia de una variable existente.

Por ejemplo

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

Tenga en cuenta que deberá incluir <boost/make_shared.hpp> para make_shared.

 8
Author: Lalaland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-11 18:51:07