1

我无法让 clang(Apple LLVM 版本 4.2 (clang-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))但这实际上并没有将 A 的所有权从 ptrB 移开:我仍然可以运行ptrB->f()而不会导致运行时崩溃......其次,构造函数不是很令人满意,因为我想隐藏std::move类接口中的实现。

提前致谢。

4

1 回答 1

2

由于 ptrB 是按值传递给 Cl 的复制构造函数的,因此对 Cl(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::move()之后保持未指定但有效的状态。我相信这意味着你仍然可以调用 ptrB->f(),并且保证返回 2 :)

于 2013-07-18T18:24:41.797 回答