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

svi*_*ick 57 c++ unique-ptr c++11 visual-studio-2012

我试图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);
Run Code Online (Sandbox Code Playgroud)

如果我正确理解了这个答案,那么这段代码应该可行,但它会导致以下编译错误:

错误C2664:'f':无法将参数1从'std :: unique_ptr <_Ty>'转换为'const std :: unique_ptr <_Ty>&'

IntelliSense:没有合适的用户定义转换,从"std :: unique_ptr <Derived,std :: default_delete <Derived >>"到"const std :: unique_ptr <Base,std :: default_delete <Base >>"存在

如果我改变f采取unique_ptr<Derived> const &derived,它工作正常,但这不是我想要的.

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

我正在使用Visual Studio 2012.

Ker*_* SB 61

你有三个选择:

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

    f(std::move(derived));
    
    Run Code Online (Sandbox Code Playgroud)
  2. 更改签名f:

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

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
    
    Run Code Online (Sandbox Code Playgroud)

    或者当然只是:

    std::unique_ptr<base> derived(new Derived);
    
    Run Code Online (Sandbox Code Playgroud)

    甚至:

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

    void f(Base & b);
    
    f(*derived);
    
    Run Code Online (Sandbox Code Playgroud)

  • @svick,为什么如果它没有取得指针的所有权,则传入一个指向函数的智能指针?这不是智能指针的用途. (9认同)
  • 如何使用引用而不是unique_ptr进行函数调用? (4认同)
  • 在这种情况下,我正在考虑使用 4. 使用 `shared_ptr`。 (2认同)
  • @metal:太棒了,谢谢 - 是的,重要的细节,回归类型必须匹配.我错过了.好东西.你可以说`return std :: unique_ptr <Base>(std :: move(p))`,我想. (2认同)

Dav*_*vid 27

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

class Derived : Base {};
Run Code Online (Sandbox Code Playgroud)

代替

class Derived : public Base {};
Run Code Online (Sandbox Code Playgroud)


hmj*_*mjd 9

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


Herb Sutter讨论了在智能指针参数中传递智能指针参数的过程.链接文章的摘录指的是这种情况:

传递a const unique_ptr<widget>&很奇怪,因为它只能接受其中任何一个null或者widget其生命周期恰好通过a来管理在调用代码中unique_ptr,并且被调用者通常不应该关心调用者的生命周期管理选择.传递widget*涵盖了这些情况的严格超集,并且可以接受" nullwidget",而不管呼叫者恰好使用的生命周期策略.

  • @svick 不。智能指针是通过明确谁是对象的所有者来避免内存泄漏。如果您将原始指针作为参数传递给函数,您只需授予读取/修改它的权限。智能指针是避免使用原始的 `new` 和 `delete`,而不是指针。 (2认同)