错误:调用隐式删除的复制构造函数&#39; std :: __ 1 :: unique_ptr <a,std :: __ 1 :: default_delete <a =“”>&gt;&#39;

时间:2016-09-27 12:09:07

标签: c++ xcode c++11

我构建一个以std::vector<std::unique_ptr<A> >为参数的对象。构造函数定义如下

class B {
    std::vector <std::unique_ptr<A> > e_;

public:
    B(std::vector <std::unique_ptr<A> > e) : e_(std::move(e)){}

};

然后用作

std::vector <std::unique_ptr<A> > e;
B b(e);

和Xcode显示错误

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >'
:new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                 ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

即使我使用std::move()

,为什么错误仍然存​​在?

编辑:如果我使用B b(std::move(e))而不是B b(e)),错误似乎消失了,有没有办法将move逻辑移动到函数的实现中?

3 个答案:

答案 0 :(得分:5)

您的构造函数参数是按值传递的,它将复制,但您无法复制std :: unique_ptr。通过引用传递应该有效:

class B {
    std::vector <std::unique_ptr<float> > e_;

public:
    B(std::vector <std::unique_ptr<float> >& e) : e_(std::move(e)){}

};

但是......我同意其他评论说这是糟糕的设计。如果您希望B拥有e但又希望在e之外操纵B,那么它应该是公共成员,不需要花哨的构造函数:

class B {
public:
    std::vector <std::unique_ptr<float> > e_;
};

答案 1 :(得分:1)

  

为什么即使我使用std :: move()?

,错误仍然存​​在

因为您正在将B的ctor的参数移动到成员中,这并不意味着应该或可以移动变量e

  

有没有办法将移动逻辑移动到函数的实现?

即使有可能,也不应该这样做。对于使用e的代码的读者应该清楚,它已被移动并且不能再使用了。

答案 2 :(得分:1)

正如前面的答案所暗示的,问题是您无法复制std::unique_ptr。按值传递构造函数参数将触发复制。话虽这么说,如果打算让B拥有unique_ptr,那么正确的方法就是使用B b(std::move(e))

与某些评论相反,这实际上是Herb Sutter建议的设计:https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/。通过值传递unique_ptr可以清楚地表明,构造函数将对象的所有权从调用者手中夺走了。此外,由于编译器需要显式的std::move,因此在代码中清楚地记录了语义。也就是说,对于用户来说,unique_ptr很明显由于显式std::move而被构造函数调用无效。