返回 std::make_unique<SubClass> 如何工作?

新手上路,请多包涵

我有一个基类及其子类:

 class Base {
    public:
    virtual void hi() {
        cout << "hi" << endl;
    }
};

class Derived : public Base {
    public:
    void hi() override {
        cout << "derived hi" << endl;
    }
};

尝试创建一个辅助函数来创建派生对象的唯一指针。

1)这个有效:

 std::unique_ptr<Base> GetDerived() {
    return std::make_unique<Derived>();
}

2)但是,这个编译失败:

 std::unique_ptr<Base> GetDerived2() {
    auto a = std::make_unique<Derived>();
    return a;
}

  1. std::move 有效:
 std::unique_ptr<Base> GetDerived3() {
    auto a = std::make_unique<Derived>();
    return std::move(a);
}

4)如果我创建一个 Base 实例,两者都可以工作:

 std::unique_ptr<Base> GetDerived4() {
    auto a = std::make_unique<Base>();
    return a;
}

std::unique_ptr<Base> GetDerived5() {
    auto a = std::make_unique<Base>();
    return std::move(a);
}

为什么(2)失败但其他人工作?

原文由 MaxHeap 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 978
2 个回答

std::unique_ptr 不可复制,只能移动。您可以从声明为返回 std::unique_ptr<Base> return std::make_unique<Derived> 函数中获得 --- 的原因是存在从一个到另一个的转换。

所以 1) 相当于:

 std::unique_ptr<Base> GetDerived() {
    return std::unique_ptr<Base>(std::make_unique<Derived>());
}

由于从 std::make_unique 返回的值是一个右值,所以返回值是移动构造的。

将其与 2) 进行对比,相当于:

 std::unique_ptr<Base> GetDerived2() {
    std::unique_ptr<Derived> a = std::make_unique<Derived>();
    return std::unique_ptr<Base>(a);
}

由于 a 是一个左值,返回值必须是复制构造的,而 std::unique_ptr 是不可复制的。

  1. 之所以有效,是因为您将左值 a 转换为右值,并且可以移动构造返回值。

  2. 和 5) 工作,因为你已经有一个 std::unique_ptr<Base> 并且不需要构造一个来返回。

原文由 Miles Budnek 发布,翻译遵循 CC BY-SA 4.0 许可协议

在上面列出的示例中,(1) 返回一个右值,但 (2) 不是一个右值,并且正在尝试对 unique_ptr 进行复制,而对于 unique_ptr 则不能这样做。

使用 move 有效,因为您将此时的 unique_ptr 视为右值。

原文由 AhiyaHiya 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题