c++ visual-studio-2012 c++11 unique-ptr

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:

  1. 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));

  2. Cambiar la firma de f :

    void f(std::unique_ptr<Derived> const &);

  3. 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>();

  4. 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 un widget null o cuya vida se administre en el código de llamada a través de un unique_ptr , y el destinatario generalmente no debería preocuparse por la opción de administración de por vida de quien realiza la llamada. El widget* pasada widget* cubre un superconjunto estricto de estos casos y puede aceptar " null o un widget " independientemente de la política de por vida que la persona que llama esté usando.