使用std::unique_ptr<T>&
代替std::unique_ptr<T>
有什么好处吗?例如,在函数参数中?
答案 0 :(得分:8)
有几种不同的情况
std::unique_ptr<T>
std::unique_ptr<T> &
T &
,然后在呼叫站点取消引用T *
并在呼叫站点呼叫unique_ptr::get
const T &
,然后在呼叫站点取消引用const T *
并在呼叫站点呼叫unique_ptr::get
T
,然后在呼叫站点取消引用<algorithm>
的集合上进行了for-for循环(或unique_ptr<T>
调用),并且想要观察值,而没有ranges::indirect
(或{{ 3}})
auto &
,并且知道它被推断为std::unique_ptr<T> &
(如果集合是const std::unique_ptr<T> &
,则推断为const
),因此您必须在循环主体中取消引用< / li>
答案 1 :(得分:4)
由于设计无法复制std::unique_ptr
,因此只能通过将指针的所有权传递给该函数来调用采用std::unique_ptr<T>
的函数(即,移动构造)。调用代码将不再能够访问指针。
使用std::unique_ptr<T>&
,您允许该函数“查看”指针并访问其成员,但是调用代码保留所有权,因此仍然可以自己使用它。
答案 2 :(得分:1)
std :: unique_ptr只能移动,因此,如果按值传递unique_ptr,则在函数调用后无法提取其内容,但如果按引用传递,则可以检索值。以下是相同的示例代码:
#include <iostream>
#include <memory>
void changeUniquePtrReference(std::unique_ptr<int>& upr)
{
*upr = 9;
}
void changeUniquePtrValue(std::unique_ptr<int> upv)
{
*upv = 10;
}
int main()
{
std::unique_ptr<int> p(new int);
*p =8;
std::cout<<"value of p is "<<*p<<std::endl;
changeUniquePtrReference(p);
std::cout<<"value of p is "<<*p<<std::endl;
changeUniquePtrValue(std::move(p));
std::cout<<"Memory deallocated so below line will crash.. "<<std::endl;
std::cout<<"value of p is "<<*p<<std::endl;
return 0;
}
答案 3 :(得分:1)
这两个变体不同,并适用于特定情况。
如果函数采用Label
,则意味着您对托管对象拥有所有权,并将其删除或保存到其他位置。
如果您使用std::unique_ptr<T>
,则不会拥有所有权,但是可以更改指针指向的内容,例如通过将其重置为其他对象。
如果您不打算更改指针本身,则只需传递std::unique_ptr<T> &
或const T&
,这取决于您是否打算修改对象。传递T&
是没有用的,因为这样做不能使您除使用const std::unique_ptr<T> &
以外还可以做更多的事情,其缺点是可能存在额外的间接调用和对参数的不必要限制。
答案 4 :(得分:0)
Herb Sutter解释了将智能指针传递给具有所有可能变化的函数的所有缺点和优点。请阅读该文章以获取更多信息,它的确很棒:
简而言之,将unique_ptr
传递给不带引用的函数是没有意义的,除非您的预期行为是放弃指针的所有权。!
答案 5 :(得分:0)
就个人而言,我只看到一种情况,您 应该 传递对unique_ptr的引用:也就是说,当您调用的方法可能在内部 > 决定以删除或放弃该对象。这应该是非常罕见的,因为所有者正在放弃所有权的决定,老实说这不是一个好的设计。
如果子对象始终取消所有权或删除该对象,则参数类型应为unique_ptr 值并立即传递所有权。
如果子对象只想访问指针内容,则参数应为 raw 指针。您可以为const unique_ptr reference
设置参数,这将阻止您释放它,但是这样做有什么意义呢?您可以修饰该原始指针类型的名称,这样,如果您觉得除原始之外还需要一个约定,就知道您不拥有它。