【问题标题】:Passing unique_ptr<Derived>& to a function accepting unique_ptr<Base>&将 unique_ptr<Derived>& 传递给接受 unique_ptr<Base>& 的函数
【发布时间】:2018-03-12 13:12:18
【问题描述】:

我需要通过引用一个函数将唯一指针传递给派生类,该函数接受对基类的唯一指针的引用,如下所示:

#include <memory>

using namespace std;

class Base {};
class Derived : public Base {};

void foo(std::unique_ptr<Base>& d){}

int main()
{
    unique_ptr<Derived> b = make_unique<Derived>();
    foo(b);
}
  1. 为什么这段代码不起作用?我查看了this one 之类的其他帖子,答案似乎是“因为 C++ 希望类型完全匹配”,但这是为什么呢?我可能会造成什么危险情况?

  2. 如果我这样做,它会编译:

    void foo(unique_ptr<Base>&& d){}
    foo(move(b));
    

    这是一个合理的方法吗?

【问题讨论】:

  • 为什么不直接接受Base&amp;?你对函数中的unique_ptr 做了什么?
  • 然后按值取unique_ptr
  • @Valentin 但是有一个移动构造函数。您希望foo 拥有指针的所有权,不是吗?按值取值,调用为foo(std::move(b))
  • 然后在调用点移动它。
  • 至于为什么您的原始方法不起作用:std::uniqe_ptr&lt;Base&gt;std::unique_ptr&lt;Derived&gt; 是两个截然不同的、不相关的类。即使Derived 是从Base 派生的,std::unique_ptr&lt;Derived&gt; 也不是从std::uniqe_ptr&lt;Base&gt; 派生或以其他方式与std::uniqe_ptr&lt;Base&gt; 相关的。它不起作用的原因与您不能将 Apple 的实例传递给采用 Orange&amp; 的函数的原因相同。

标签: c++ c++11 move smart-pointers


【解决方案1】:

我可能会造成什么危险情况?

想象一下 foo 的以下实现:

void foo(std::unique_ptr<Base>& d){
    d.reset(new Base);
}

你现在有一个std::unique_ptr&lt;Derived&gt; 指向一个不是Derived 类型的对象,编译器无法给你任何警告。

如 cmets 中所述,解决问题的正确方法是按值获取 std::unique_ptr&lt;Base&gt;,并将其移动到调用站点。

void foo(std::unique_ptr<Base> d) {
    // move d to your list
}

int main() {
    unique_ptr<Derived> b = make_unique<Derived>();
    foo(std::move(b));
}

【讨论】:

    【解决方案2】:

    从 Derived 到 Base 的简单 static_cast 以及适当的释放调用(将资源的所有权转移到新创建的指针)应该可以正常工作。

    int main()
    {
        unique_ptr<Derived> b = make_unique<Derived>();
        std::unique_ptr<Base> basePointer(static_cast<Base*>(b.release()));
        foo(basePointer);
    }
    

    【讨论】:

    • 你认为foo(std::move(b));是多余的,但std::unique_ptr&lt;Base&gt; basePointer(static_cast&lt;Base*&gt;(b.release())); foo(basePointer);不是?
    • 技术上两者是相同的。编辑了我的答案。我有一种挥之不去的感觉,认为此举可能是一种矫枉过正......并且可能会导致异常,以防错过 b 的隐式转换,并使用它。 (发布调用使它有点明确)。
    猜你喜欢
    • 2018-12-15
    • 2014-03-27
    • 2021-10-09
    • 2019-05-24
    • 2014-07-21
    • 2012-03-30
    • 2020-09-29
    • 1970-01-01
    • 2020-01-30
    相关资源
    最近更新 更多