Tengo una clase Object que es muy costosa de copiar. Escribí una función que toma una referencia constante a Object como argumento de función. Ahora en la función necesito llamar a una función que toma un puntero compartido a Object. ¿Cómo puedo llamar a esta función sin copiar todo el objeto al menos una vez?

-1
user3726947 13 ene. 2018 a las 23:58

3 respuestas

La mejor respuesta

Puede usar el constructor de alias del puntero compartido:

void f(std::shared_ptr<X>);  // the other function

void my_function(const X& x)
{
    f(std::shared_ptr<X>(nullptr, &x));
}

Sin embargo, tenga en cuenta que no está claro que esto sea correcto: es vital en esta situación que nada debajo de f tome acciones de propiedad que se extiendan más allá de la vida real de x en su función. Si f está diseñado correctamente, entonces es lógico que espere un puntero compartido para que pueda tomar arbitrariamente recursos compartidos de por vida adicionales, por lo que solo lo usaría con extrema precaución.

La única solución "correcta" (que no sea cambiar la firma de su función) es administrar realmente la vida útil del objeto en cuestión con un puntero compartido, y quizás agregar una función enable_shared_from_this a X:

void my_function(const X& x)
{
    f(x.shared_from_this());  // X must be changed to support this
}
4
Kerrek SB 13 ene. 2018 a las 21:05

Tome la dirección de la referencia, haga un const_cast para deshacerse del const y luego pase un borrador nulo junto con el puntero al constructor del puntero inteligente. Un borrador nulo es un borrador que no realiza ninguna acción. es decir

std::shared_ptr(const_cast<my_type*>(&myRef), [] (my_type *) { })

Tenga en cuenta que si la función a la que está pasando realmente espera realizar una gestión de por vida en el parámetro, puede terminar necesitando copiar el objeto.

-1
SoronelHaetir 13 ene. 2018 a las 21:06

Por supuesto, puedes hacer algo así:

#include <memory>

struct Obj
{
};

void f(const Obj &o)
{
    std::shared_ptr<const Obj> optr(&o, [](const Obj*){});
}
-2
A.N. 13 ene. 2018 a las 21:22
48244251