c++ - unique_ptr a una clase base
visual-studio-2012 c++11 (2)
unique_ptr
utilizar un unique_ptr
para la clase derivada en una función que toma un unique_ptr
para una clase base. Algo como:
class Base {};
class Derived : public Base {};
void f(unique_ptr<Base> const &base) {}
…
unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived);
f(derived);
Si entiendo esta respuesta correctamente, este código debería funcionar, pero causa los siguientes errores de compilación:
error C2664: ''f'': no se puede convertir el parámetro 1 de ''std :: unique_ptr <_Ty>'' a ''const std :: unique_ptr <_Ty> &''
IntelliSense: no existe una conversión adecuada definida por el usuario de "std :: unique_ptr <Derived, std :: default_delete <Derived >>" a "const std :: unique_ptr <Base, std :: default_delete <Base >>"
Si cambio f
para tomar unique_ptr<Derived> const &derived
, funciona bien, pero eso no es lo que quiero.
¿Estoy haciendo algo mal? ¿Qué puedo hacer para evitar esto?
Estoy usando Visual Studio 2012.
Tienes tres opciones:
Renunciar a la propiedad. Esto dejará su variable local sin acceso al objeto dinámico después de la llamada a la función; el objeto ha sido transferido al destinatario:
f(std::move(derived));
Cambiar la firma de
f
:void f(std::unique_ptr<Derived> const &);
Cambia el tipo de tu variable:
std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
O, por supuesto, solo
std::unique_ptr<base> derived(new Derived);
O incluso:
std::unique_ptr<base> derived = std::make_unique<Derived>();
Actualización: O, como se recomienda en los comentarios, no transfiera la propiedad en absoluto:
void f(Base & b); f(*derived);
Una solución posible es cambiar el tipo de argumento para que sea una Base const*
, y pase derived.get()
lugar. No hay transferencia de propiedad con unique_ptr const<Base>&
(y unique_ptr
no se está modificando), por lo tanto, cambiar a una Base const*
no cambia el significado.
Herb Sutter analiza el paso de los argumentos del puntero inteligente en longitud en los Parámetros de Smart Pointer . Un extracto del artículo vinculado se refiere a esta situación exacta:
Pasar un
const unique_ptr<widget>&
es extraño porque solo puede aceptar unwidget
null
o cuya vida se administre en el código de llamada a través de ununique_ptr
, y el destinatario generalmente no debería preocuparse por la opción de administración de por vida de quien realiza la llamada. Elwidget*
pasadawidget*
cubre un superconjunto estricto de estos casos y puede aceptar "null
o unwidget
" independientemente de la política de por vida que la persona que llama esté usando.