返回 std::move 具有 unique_ptr 成员的类

vox*_*oid 1 c++ unique-ptr stdmove

为什么我不能std::unique_ptr使用std::move语义(我认为)返回包含 , 的类,如下例所示?我认为 return 会调用 class 的 move ctor A,这将std::movestd::unique_ptr. (我使用的是 GCC 11.2,C++20)

例子:

#include <memory>

class A {
  public:
    explicit A(std::unique_ptr<int> m): m_(std::move(m)) {}
  private:
    std::unique_ptr<int> m_;
};

A makit(int num) {
    auto m = std::make_unique<int>(num);
    return std::move(A(m));  // error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'x86-64 gcc 11.2 #1
}

int main() {
    auto a = makit(42);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我相信解决方案是返回 a std::unique_ptr,但在我屈服之前我想知道为什么这种std::move方法不起作用。

Sto*_*ica 5

我认为 return 会调用 A 类的 move ctor,这将std::movestd::unique_ptr.

全部正确,但移动构造函数仅移动 的成员A。它无法为您移动不相关的卫星唯一指针。

在表达式 中A(m),您用作m左值。这将尝试复制m以初始化参数mA::A顺便说一句,对于所有这些的推理来说,可怕的命名方案)。如果移动,即A(std::move(m))表达式就会变得格式良好。

在这个问题上,外在std::movestd::move(A(...))多余的。A(...)已经是类型的右值A。额外的东西std::move在这里没有任何好处。