CppCoreGuidlines R.33 为什么要通过引用传递“unique_ptr”?

CppCoreGuidlines R.33 Why pass `unique_ptr` by reference?

提问人:evolved 提问时间:9/24/2021 更新时间:9/24/2021 访问量:270

问:

CppCoreGuidlines 规则 R.33 建议

取一个参数来表示一个函数 重新拔插小部件。unique_ptr<widget>&

原因 以这种方式使用既记录又强制执行 函数调用的重新嵌插语义。unique_ptr

注意“重新拔插”是指“使指针或智能指针指引 不同的对象。

我不明白为什么当 reseat 意味着“使指针或智能指针引用不同的对象”时,我们应该通过引用来传递。

当函数的目的是重新驻插/更改指针指向的基础对象时,我们不是以这种方式从调用者那里窃取所有权,因此应该传递 by 值,从而移动它并转移所有权吗?unique_ptr

有没有一个例子可以解释为什么建议通过引用传递?unique_ptr

C++ C++11 cpp-core-guidelines

评论

4赞 molbdnilo 9/24/2021
关键是不要转让所有权。调用方保留对象的所有权,但该函数将其替换为其他对象。
0赞 Alan Birtles 9/24/2021
如果你按值传递,那么你根本无法更改指针?
0赞 Some programmer dude 9/24/2021
因为这将允许“重新插入”函数(被调用的函数)实际重新插入指针?即重置它并使其指向其他地方。
0赞 evolved 9/24/2021
如果我们把它指向其他地方,它之前指向的对象会发生什么?在这种情况下,我们不是在泄漏内存吗?
1赞 Some programmer dude 9/24/2021
重置智能指针可以执行正确的操作,并处理释放旧对象。

答:

2赞 eerorika 9/24/2021 #1

当函数的目的是重新插入/更改指针指向的基础对象时,我们不是以这种方式从调用者那里窃取所有权吗

不。无论是当我们“重新放置”指针时,还是当我们更改指向的对象时,我们都不会获得指针的所有权,即我们没有转移所有权。

有没有一个例子可以解释为什么建议通过引用传递unique_ptr?

下面是“重新拔插”唯一指针的函数示例:

void reseat(std::unique_ptr<widget>& ptr) {
    ptr = std::make_unique<widget>();
}

如果您尝试使用对 const 的引用,则根本无法编译。如果尝试使用非引用参数,则不会修改参数指针,因此行为不会达到预期效果。调用方将被迫移动其指针,使其始终为 null。

您可以修改该示例以使用指向唯一指针的指针,但建议使用引用,因为不可能错误地传递 null。引用包装器也可以工作,但它会不必要地复杂。

如果我们把它指向其他地方,它之前指向的对象会发生什么?

如果唯一指针指向 null 以外的内容,则将其指向其他位置将导致删除以前指向的对象。

在这种情况下,我们不是在泄漏内存吗?

不。


请注意,为了便于理解,该示例很简单。通常,我不建议编写这样的函数,而是考虑编写一个返回新唯一指针的函数,并让调用者自己“重新替换”指针。但这取决于细节。

评论

0赞 evolved 9/24/2021
除了使用 之外,还可以使用 重新替换底层对象,而不是在函数内部创建一个新的?unique_ptrreseatstd::make_uniquestd::unique_ptr::reset
0赞 eerorika 9/24/2021
@evolved 的用法意味着您有一个拥有的裸指针作为参数传递给(除非您重置为 null)。我建议首先不要拥有裸指针。但是,是的,这是可能的。resetreset
0赞 evolved 9/24/2021
我们多久发生一次函数,我们通过引用传递 a 来重新替换小部件?这是现代 C++ 中的常见做法吗?或者您是否还建议不要通过引用传递唯一指针,而让调用方重新拔插?unique_ptr
0赞 j6t 9/24/2021
一种常见的情况是,仅根据某些条件有时才进行重新拔插。
0赞 eerorika 9/24/2021
@evolved 你必须向研究过C++中参数使用频率的人提出这个问题。这并不是什么不寻常的事情。