如何将 std::unique_ptr 传递到函数中
How can I pass std::unique_ptr into a function
如何将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)));
这里基本上有两个选项:
通过引用传递智能指针
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)
}
您按值传递它,这意味着制作副本。这不会很独特,不是吗?
您可以移动该值,但这意味着将对象的所有权及其生存期的控制权传递给函数。
如果对象的生存期保证在调用 MyFunc 的生存期内存在,则只需通过 ptr.get()
传递原始指针。
为什么不能将
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));
重要说明
请注意,如果使用第二种方法,则在调用 std::move(ptr)
返回后,ptr
没有指针的所有权。
void MyFunc(std::unique_ptr<A>&& arg)
将具有与void MyFunc(std::unique_ptr<A>& arg)
相同的效果,因为两者都是引用。
在第一种情况下,ptr
在调用 MyFunc
后仍然拥有指针的所有权。
由于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
没有故意复制以保证只有一个所有者。
为什么我不能将
unique_ptr
传递到函数中?
你可以,但不能通过复制 - 因为std::unique_ptr<>
不是可复制构造的。
这肯定是构造的主要目的吗?
除此之外,std::unique_ptr<>
旨在明确标记唯一所有权(而不是std::shared_ptr<>
)。
最奇怪的是,为什么这是一种可以传递它的方式?
因为在这种情况下,没有复制构造。
由于unique_ptr
用于唯一所有权,如果您想将其作为参数传递,请尝试
MyFunc(move(ptr));
但在那之后,main
的ptr
状态将是nullptr
.
为了捎带现有的答案,C++智能指针与所有权的概念密切相关。你的代码应该清楚地表达你与将所有权传递给或不传递给另一个组件(即函数、线程等)相关的信息,这就是为什么有独特的、共享的和弱指针的原因。唯一指针已经表明,在某一时刻只有一个组件拥有该指针的所有权,因此唯一所有权不能共享,只能移动。也就是说,当前拥有指针的所有者在脱离上下文时会自行销毁它,通常在块的末尾或在析构函数中。将对象传递给另一个函数可能意味着共享或移动所有权。如果您确定所有者在通过引用调用函数时不会脱离上下文,则可以通过引用调用,但这很丑陋。它添加了一些前置条件和后置条件,会增加代码的不动性,同时还会破坏指针的智能性,指针或多或少地调整为原始指针。例如,更改"函数"以在另一个线程中启动和执行自己的内容不再可能。由于在代码的某些非常包含的部分中,通过引用传递仍然是一种选择,即寻找节省从唯一指针到共享指针来回移动的额外开销,因此我会高度避免它,尤其是在公共接口中。
std::unique_ptr<T>
作为值传递给函数是行不通的,因为正如你们提到的,unique_ptr
是不可复制的。
这个呢?
std::unique_ptr<T> getSomething()
{
auto ptr = std::make_unique<T>();
return ptr;
}
此代码正在工作
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 视觉 C++编译器在计算其参数之前是否允许将函数 ptr 存储在寄存器中?
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 通过成员函数将唯一 ptr 的向量附加到另一个向量
- 如何将函数 ptr 分配给函数 ptrs 数组(Arduino C++)
- 带智能ptr的Pimpl-为什么需要构造函数/析构函数
- 如何将shared_ptr传递给裸 ptr 函数
- 将 lamba 隐式转换为函数 ptr 以创建类
- c++在没有虚拟析构函数的多态性中共享ptr
- 如何调用传递的函数(函数 ptr 作为参数传递给函数)
- OpenCL enqueueWriteImage no const void* ptr 在包装器中C++但在 C 函数中
- 正在从DLL获取函数PTR
- 从虚拟成员函数ptr中进行类型推导(bug?)
- 为什么这个显式析构函数会导致共享ptr中的内存损坏
- 如何访问受保护的基类函数,从派生类通过基类ptr
- openv Ptr类.指针对象在调用函数后被删除
- 函数PTR转换为带模板参数的函数
- 删除从函数返回的唯一ptr
- 具有基类唯一ptr的类的复制构造函数