unique_ptr到派生类,作为将unique_ptr带到基类的函数的参数

时间:2013-07-04 15:29:31

标签: c++ visual-studio-2012 c++11 unique-ptr

我正在尝试在一个将unique_ptr带到基类的函数中使用unique_ptr派生类。类似的东西:

class Base {};

class Derived : public Base {};

void f(unique_ptr<Base> const &base) {}

…

unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived);
f(derived);

如果我正确理解this answer,这段代码应该可行,但会导致以下编译错误:

  

错误C2664:'f':无法从'std :: unique_ptr&lt; _Ty&gt;'转换参数1到'const std :: unique_ptr&lt; _Ty&gt; &安培;'

     

IntelliSense:没有合适的用户定义转换来自“std :: unique_ptr&lt; Derived,std :: default_delete&lt; Derived&gt;&gt;” to“const std :: unique_ptr&lt; Base,std :: default_delete&lt; Base&gt;&gt;”存在

如果我将f更改为unique_ptr<Derived> const &derived,则可以正常使用,但这不是我想要的。

我做错了吗?我该怎么做才能解决这个问题?

我正在使用Visual Studio 2012。

4 个答案:

答案 0 :(得分:53)

您有三种选择:

  1. 放弃所有权。在函数调用之后,这将使您的局部变量无法访问动态对象;对象已被转移到被调用方:

    f(std::move(derived));
    
  2. 更改f的签名:

    void f(std::unique_ptr<Derived> const &);
    
  3. 更改变量的类型:

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
    

    当然只是:

    std::unique_ptr<base> derived(new Derived);
    

    甚至:

    std::unique_ptr<base> derived = std::make_unique<Derived>();
    
  4. 更新或者,根据评论中的建议,根本不转让所有权:

    void f(Base & b);
    
    f(*derived);
    

答案 1 :(得分:9)

可能的解决方案是将参数的类型更改为Base const*,然后传递derived.get()unique_ptr const<Base>&没有转让所有权(并且unique_ptr未被修改),因此更改为Base const*不会改变其含义。


Herb Sutter讨论了Smart Pointer Parameters中传递智能指针参数的问题。链接文章的摘录指的是这种情况:

  

传递const unique_ptr<widget>&很奇怪,因为它只能接受nullwidget,其生命周期恰好通过unique_ptr在调用代码中进行管理,并且被调用者一般不应该关心来电者的终身管理选择。传递widget*涵盖了这些情况的严格超集,并且可以接受“nullwidget”,而不管调用者恰好使用的生命周期策略。

答案 2 :(得分:1)

我有接受答案的选项#1,但仍然有相同的编译错误。我把头撞在墙上一个多小时,我终于意识到我有

class Derived : Base {};

代替

class Derived : public Base {};

答案 3 :(得分:0)

另一种方法是更改​​ f 的签名并以稍微不同的方式使用它:

void f(Base* base_ptr) {
    // take ownership inside the function
    std::unique_ptr<Base> base {base_ptr};
    // ...
}

// ...
auto derived = std::make_unique<Derived>();
f(derived.release());  // release ownership