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

use*_*202 63 c++ unique-ptr c++11

我怎样才能将std::unique_ptr函数传递给函数?可以说我有以下课程:

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

    int GetVal() { return _val; }
private:
    int _val;
};
Run Code Online (Sandbox Code Playgroud)

以下内容无法编译:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

MyFunc(&(*ptr)); 
Run Code Online (Sandbox Code Playgroud)

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

MyFunc(unique_ptr<A>(new A(1234)));
Run Code Online (Sandbox Code Playgroud)

Bil*_*nch 92

这里基本上有两种选择:

通过引用传递智能指针

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);
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,在这种情况下,断言将成立!

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)
}
Run Code Online (Sandbox Code Playgroud)

  • 听听Herb Sutters关于CppCon 2014的演讲.他强烈反对,传递对unique_ptr <>的引用.重要的是,在处理所有权时,您应该使用诸如unique_ptr <>或shared_ptr <>之类的智能指针.请访问www.youtube.com/watch?v=xnqTKD8uD64您可以在这里找到幻灯片https://github.com/CppCon/CppCon2014/tree/master/Presentations/Back%20to%20the%20Basics!%20Essentials%20of%20Modern %20C%2B%2B%20Style (7认同)
  • 如果函数可能会或可能不会从中移动,则只应通过引用传递`unique_ptr`.然后它应该是一个右值参考.要观察一个对象而不需要任何关于其所有权语义的东西,请使用像"A const&"或"A&"这样的引用. (6认同)
  • 谢谢。在本例中,我想创建一个实例,对其执行一些操作,然后将所有权传递给其他人,move() 似乎非常适合。 (2认同)
  • @Furihr:这只是一种显示移动后`ptr`的价值的方式. (2认同)

Mar*_*nen 22

你按价值传递它,这意味着制作副本.这不是很独特,不是吗?

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

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

  • @Triskeldeian 这就是问题的重点。按照OP的方式传递“unique_ptr”*确实*意味着一个副本并且不起作用,显然是由于没有复制构造函数。我*确实*提到他们可以转移价值,但会转移所有权。 (2认同)

R S*_*ahu 15

为什么我不能传入unique_ptr函数?

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

12.8复制和移动类对象

...

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

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

void MyFunc(std::unique_ptr<A>& arg)
{
    cout << arg->GetVal() << endl;
}
Run Code Online (Sandbox Code Playgroud)

并像你一样使用它:

要么

void MyFunc(std::unique_ptr<A> arg)
{
    cout << arg->GetVal() << endl;
}
Run Code Online (Sandbox Code Playgroud)

并使用它像:

std::unique_ptr<A> ptr = std::unique_ptr<A>(new A(1234));
MyFunc(std::move(ptr));
Run Code Online (Sandbox Code Playgroud)

重要的提示

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

void MyFunc(std::unique_ptr<A>&& arg)会有同样的效果,void MyFunc(std::unique_ptr<A>& arg)因为两者都是引用.

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


Nie*_*elk 6

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

您可以,但不能通过复制 - 因为std::unique_ptr<>不可复制构造。

这肯定是构造的主要目的吗?

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

最奇怪的是,为什么这是通过它的好方法?

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

  • 因为它是一个右值,所以调用移动构造函数。尽管您的编译器肯定会对此进行优化。 (2认同)

Jar*_*d42 6

由于MyFunc不拥有所有权,最好拥有:

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

或更好

void MyFunc(const A& arg)
{
    cout << arg.GetVal() << endl;
}
Run Code Online (Sandbox Code Playgroud)

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

std::unique_ptr<A> ptr = std::make_unique<A>(1234);
MyFunc(std::move(ptr));
Run Code Online (Sandbox Code Playgroud)

或直接传递 r 值引用:

MyFunc(std::make_unique<A>(1234));
Run Code Online (Sandbox Code Playgroud)

std::unique_ptr 没有故意复制以保证只有一个所有者。