作为的unique_ptr类成员和移动语义失败,铛编译(unique_ptr as class me

2019-10-18 10:02发布

我不能让铛(苹果LLVM 4.2版(铛-425.0.28))编译这些类:

struct A {
    int f(){return 2;}
};
class Cl{
     std::unique_ptr<A> ptr;

public:
     Cl(){ptr = std::unique_ptr<A>(new A);}

     Cl(const Cl& x) : ptr(new A(*x.ptr)) { }
     Cl(Cl&& x) : ptr(std::move(x.ptr)) { }
     Cl(std::unique_ptr<A> p) : ptr(std::move(p))  { }

    void m_ptr(std::unique_ptr<A> p){
        ptr = std::unique_ptr<A>(std::move(p));
    }
    double run(){return ptr->f();}
};

我想运行构造函数如下:

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(ptrB);

但如果我这样做,我得到以下编译器错误:../src/C++11-2.cpp:66:10:错误:调用“的std ::的unique_ptr” C.m_ptr的隐含缺失的拷贝构造函数(的ptrB);

我可以通过运行解决问题编译Cl(std::move(ptrB))但这实际上并没有从移动的ptrB的客场所有权:我仍然可以运行ptrB->f()而不会导致运行时崩溃......其次,构造也不是很满意的,因为我想隐藏实施std::move的类接口。

提前致谢。

Answer 1:

由于是的ptrB 按值传递给氯的拷贝构造函数,对氯的调用(的ptrB)尝试创建的ptrB的副本,后者又调用一个(显然禁用)复制的unique_ptr的构造函数。 为了避免产生的ptrB的额外副本,请执行以下操作:

Cl C = Cl(std::unique_ptr<A>(new A)); //A temporary is created on initialization, no extra copy steps performed

要么:

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(std::move(ptrB)); //Move semantics used. Again, no extra copy steps

或者,使用路过你的拷贝构造函数引用(右值或左值):

class Cl{

//...
public:
//...
     Cl(std::unique_ptr<A> &p) : ptr(std::move(p))  { }

//...

};

std::unique_ptr<A> ptrB (new A);
Cl C = Cl(ptrB);

PS哦,顺便说一下:对象停留在未指定的,但经过有效状态的std ::移动()。 我相信,这意味着你仍然可以调用ptrB-> F(),它是保证返回2 :)



文章来源: unique_ptr as class member and move semantics fail to compile with clang