如何将 std: : 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)));
147554 次浏览

基本上有两个选择:

通过引用传递智能指针

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)
}

因为 unique_ptr是唯一所有权,所以如果要将其作为参数传递,请尝试

MyFunc(move(ptr));

但在此之后,main中的 ptr状态将是 nullptr

你通过值传递它,这意味着复制一个副本。这不会是非常独特的,不是吗?

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

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

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

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

这肯定是这个建筑的主要目的吧?

在其他方面,std::unique_ptr<>的目的是明确标记 独一无二所有权(而不是 std::shared_ptr<>)。

最奇怪的是,为什么这是一种可以通过的方式?

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

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

你不能这样做,因为 unique_ptr有 move 构造函数,但没有复制建构子。根据标准,当移动构造函数被定义但是没有定义复制建构子时,复制建构子就会被删除。

12.8复制和移动类对象

...

如果类定义没有显式声明一个复制建构子,那么就会隐式声明一个。如果类定义声明了 move 构造函数或 move 赋值运算符,那么隐式声明的复制建构子就被定义为删除;

可以使用以下方法将 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));

重要提示

请注意,如果使用第二个方法,则在对 std::move(ptr)的调用返回之后,ptr不拥有指针的所有权。

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

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

由于 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没有故意复印件来保证只有一个所有者。

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

这个怎么样?

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

这个密码起作用了