如何将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)));
答案 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;
}
此代码有效