如何将std :: unique_ptr传递给函数

时间:2015-06-18 02:22:36

标签: c++ c++11 unique-ptr

如何将std::unique_ptr传递给函数?可以说我有以下课程:

class A
{
public:
    A(int val)
    {
        _val = val;
    }

    int GetVal() { return _val; }
private:
    int _val;
};

以下内容无法编译:

void MyFunc(unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(ptr);

    return 0;
}

为什么我不能将std::unique_ptr传递给函数?当然这是构造的主要目的吗?或者C ++委员会是否打算让我回到原始的C风格指针并将其传递给它:

MyFunc(&(*ptr)); 

最奇怪的是,为什么这是一种传递它的好方法?这似乎非常不一致:

MyFunc(unique_ptr<A>(new A(1234)));

7 个答案:

答案 0 :(得分:70)

这里基本上有两种选择:

通过引用传递智能指针

void MyFunc(unique_ptr<A> & arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(ptr);
}

将智能指针移动到函数参数

请注意,在这种情况下,断言将保持!

void MyFunc(unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

int main(int argc, char* argv[])
{
    unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
    MyFunc(move(ptr));
    assert(ptr == nullptr)
}

答案 1 :(得分:16)

你通过值传递它,这意味着制作副本。这不是很独特,不是吗?

您可以移动该值,但这意味着将对象的所有权和对其生命周期的控制权交给函数。

如果在MyFunc调用的生命周期内保证对象的生命周期存在,只需通过ptr.get()传递一个原始指针。

答案 2 :(得分:12)

  

为什么我不能将unique_ptr传递给函数?

你不能这样做因为unique_ptr有一个移动构造函数而不是一个复制构造函数。根据标准,当定义移动构造函数但未定义复制构造函数时,将删除复制构造函数。

  

12.8复制和移动类对象

     

...

     

7如果类定义没有显式声明复制构造函数,则会隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;

您可以使用以下命令将unique_ptr传递给该函数:

void MyFunc(std::unique_ptr<A>& arg)
{
    cout << arg->GetVal() << endl;
}

并像你一样使用它:

void MyFunc(std::unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}

并使用它:

std::unique_ptr<A> ptr = std::unique_ptr<A>(new A(1234));
MyFunc(std::move(ptr));

重要提示

请注意,如果您使用第二种方法,ptr的调用后,std::move(ptr)没有指针的所有权。

void MyFunc(std::unique_ptr<A>&& arg)void MyFunc(std::unique_ptr<A>& arg)具有相同的效果,因为它们都是引用。

在第一种情况下,ptr在调用MyFunc后仍然拥有指针的所有权。

答案 3 :(得分:4)

  

为什么我不能将 <div id="pop0" data-role="popup"> <p><a href="halifax.ca" target="_blank">Halifax's Website</a></p> </div> 传递给函数?

您可以,但不能通过复制 - 因为unique_ptr不是可复制构造的。

  

当然这是构造的主要目的吗?

除其他事项外,std::unique_ptr<>旨在明确标记唯一所有权(与std::unique_ptr<>相对)。

  

最奇怪的是,为什么这是传递它的好方法?

因为在这种情况下,没有复制构造。

答案 4 :(得分:4)

由于MyFunc没有取得所有权,最好拥有:

void MyFunc(const A* arg)
{
    assert(arg != nullptr); // or throw ?
    cout << arg->GetVal() << endl;
}

或更好

void MyFunc(const A& arg)
{
    cout << arg.GetVal() << endl;
}

如果你真的想要获得所有权,你必须移动你的资源:

std::unique_ptr<A> ptr = std::make_unique<A>(1234);
MyFunc(std::move(ptr));

或直接传递r值参考:

MyFunc(std::make_unique<A>(1234));

std::unique_ptr并非故意复制以保证只有一位所有者。

答案 5 :(得分:0)

由于unique_ptr用于唯一所有权,因此如果您想将其作为参数传递,请尝试

MyFunc(move(ptr));

但在此之后ptr中的main状态为nullptr

答案 6 :(得分:0)

std::unique_ptr<T>作为值传递给函数不起作用,因为正如你们提到的,unique_ptr是不可复制的。

那呢?

std::unique_ptr<T> getSomething()
{
   auto ptr = std::make_unique<T>();
   return ptr;
}

此代码有效