0

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

例子:

#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;
}

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

4

2 回答 2

2

我认为返回将调用 A 类的移动 ctor,这std::movestd::unique_ptr.

都是真的,但移动构造函数只移动A. 它不能为您移动不相关的卫星唯一指针。

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

在这个问题上,外部std::movestd::move(A(...))多余的。A(...)已经是 type 的右值A。额外的std::move在这里没有什么好处。

于 2021-12-07T06:13:43.027 回答
-1
  • 简而言之,你不应该A使用返回,std::move因为编译器会为你做优化工作(通过一个叫做 RVO 的技巧:什么是复制省略和返回值优化?)。

  • 另一点是std::movein是完全没有必要的,因为无论使用与否m_(std::move(m)),都会发生应对。请记住,这并不能保证移动操作,也不能在所有情况下都阻止应对。unique_ptrstd::movestd::move

总之,您最好使用return A( std::move(m) );而不是return std::move(A(m));. 在您的 return 语句中,A(m)已经是一个纯右值,并且您不需要将其强制转换为xvaluestd::move以便有效地返回它。只需按返回它,编译器就会为您解决问题。

于 2021-12-07T07:10:37.130 回答