繁体   English   中英

返回 std::move 带有 unique_ptr 成员的 class

[英]return std::move a class with a unique_ptr member

为什么我不能使用std::move语义(我认为)返回包含std::unique_ptr的 class ,如下例所示? 我认为返回会调用 class A的移动ctor,这将std::move std::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;
}

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

我认为返回会调用 class A 的移动 ctor,这将std::move std::unique_ptr

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

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

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

  • 简而言之,您不应该使用std::move返回A ,因为编译器会为您完成优化工作(通过称为 RVO 的技巧: 什么是复制省略和返回值优化? )。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM