【问题标题】:"Use of deleted function" when calling `std::unique_ptr` move constructor?调用`std :: unique_ptr`移动构造函数时“使用已删除函数”?
【发布时间】:2020-08-17 04:01:46
【问题描述】:

在定义一个对std::unique_ptr 对象进行移动引用的函数时,我遇到了编译问题。

#include <memory>

class foo {
 public:
    foo() { /* */ };
};

void function(foo&& arg) {
    foo bar(arg);
}

void function2(std::unique_ptr<foo>&& arg){
    std::unique_ptr<foo> foo(arg);
}


int main(int argc, char const *argv[]) {
    foo A;
    function(foo());
    function2(std::unique_ptr<foo>(new foo));
    return 0;
}

导致:

test.cpp: In function ‘void function2(std::unique_ptr<foo>&&)’:
test.cpp:16:30: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = foo; _Dp = std::default_delete<foo>]’
   16 |  std::unique_ptr<foo> foo(arg);
      |                              ^
In file included from /usr/include/c++/9.3.0/memory:80,
                 from test.cpp:1:
/usr/include/c++/9.3.0/bits/unique_ptr.h:414:7: note: declared here
  414 |       unique_ptr(const unique_ptr&) = delete;

我尝试通过传递对自定义类的引用来复制它,但正如预期的那样,它不会导致任何问题,因为默认移动构造函数是由编译器隐式声明的。为什么std::unique_ptr会发生这种情况? std::unique_ptr 有一个默认的移动构造函数,那么我缺少什么?

【问题讨论】:

  • function2 更好的签名是void function2(std::unique_ptr&lt;foo&gt; arg),因为它会下沉(移动)持有的对象,如果使用不正确,unique_ptr 会在调用点提供编译器错误反馈。 (std::unique_ptr&lt;foo&gt;&amp;&amp; 也是如此,但随后 function2 可能决定不移动参数而不是移动参数。)对于像 std::vector 这样的容器作为接收器 arg,我会使用 std::vector&lt;foo&gt;&amp;&amp; 作为参数,因为否则调用站点可能会默默地制作一个可能很昂贵的副本。

标签: c++ constructor smart-pointers move-semantics


【解决方案1】:

出于安全原因,我们施加了一些限制。即使声明为右值,命名变量也永远不会被视为右值。要获得右值,应使用函数模板std::move()。右值引用也只能在某些情况下修改,主要用于移动构造函数。

void function2(std::unique_ptr<foo>&& arg) {
    std::unique_ptr<foo> foo(std::move(arg));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多