将unique_ptr传递给函数

jco*_*der 46 c++ smart-pointers unique-ptr

我正试图"现代化"一些现有的代码.

  • 我有一个类,当前有一个成员变量"Device*device_".
  • 它使用new在一些初始化代码中创建一个实例,并在destructory中有一个"delete device_".
  • 此类的成员函数调用许多其他函数,这些函数将Device*作为参数.

这很好用,但为了"现代化"我的代码,我认为我应该更改要定义的变量,"std::unique_ptr<Device> device_"并删除显式调用delete,这使得代码更安全,通常更好.

我的问题是这个 -

  • 那么我应该如何将device _变量传递给需要它作为参数的所有函数?

我可以调用.get来获取每个函数调用中的原始指针.但这看起来很丑陋,浪费了一些首先使用unique_ptr的原因.

或者我可以更改每个函数,以便不使用"Device*"类型的参数,而是使用"std :: unique_ptr&"类型的参数.哪个(对我来说)有点模糊了函数原型,并使它们难以阅读.

这是什么最佳做法?我错过了其他选择吗?

Mat*_* M. 44

Modern C++风格中,有两个关键概念:

  • 所有权
  • 婚姻无效

所有权是关于某个对象/资源的所有者(在这种情况下,是一个实例Device).各种std::unique_ptr,boost::scoped_ptrstd::shared_ptr关于所有权.

然而,Nullity更简单:它只是表达给定对象是否为null,并且不关心任何其他内容,当然也不关心所有权!


你是正确的移动你的类向实施unique_ptr(一般),虽然你可能想与深拷贝语义的智能指针如果你的目标是实现一个PIMPL.

这清楚地表明,你的班级是唯一负责这段记忆的人,并且巧妙地处理了记忆本可以泄露的各种方式.


另一方面,资源的大多数用户对其所有权不太关心.

只要函数不保持对对象的引用(将其存储在映射或其他内容中),那么重要的是对象的生命周期超过函数调用的持续时间.

因此,选择如何传递参数取决于其可能的Nullity:

  • 永远不会?传递参考
  • 可能是空的?传递一个指针,一个简单的裸指针或类似指针的类(例如,在null上有一个陷阱)

  • @JohnB:在这里完全同意Matthieu,我甚至会更进一步,你为什么要动态分配一个对象,它的生命周期受到持有指针的对象的生命周期的约束?为什么不将它声明为具有自动存储的普通成员? (6认同)
  • @JohnB:嗯,我的联络观点是在编译时根除无效的可能性更安全:) (2认同)

jua*_*nza 14

这真的取决于.如果一个函数必须取得unique_ptr的所有权,那么它的签名应该是一个unique_ptr<Device>bv ,而调用者应该std::move是指针.如果所有权不是问题,那么我将保留原始指针签名并使用指针unique_ptr get().如果有问题的功能不接管所有权,这并不难看.

  • 如果所有权不是问题,您还可以将const引用传递给unique_ptr.有些人使用指针参考二分法来模拟Pascals的in-out形式参数语义(Google C++风格指南). (2认同)

mka*_*aes 7

我会用std::unique_ptr const&.使用非const引用将为被调用函数提供重置指针的可能性.
我认为这是表达被调用函数可以使用指针而不是其他任何东西的好方法.
所以对我来说这将使界面更容易阅读.我知道我不必乱用指针传给我.

  • 也许我错了,但在我看来,采用类型为`const std :: unique_ptr <T>&`的参数是_always_次优的.用你所说的`const`,我不会把你的对象(所有权)带走(调用者).但是使用`std :: unique_ptr`部分,你要说_you_必须是指向的对象的(直接)所有者.但鉴于我(称为函数)不会承担所有权,我无从知道谁拥有.请注意,如果调用者"租用"一个指针(具有访问权限但不是所有权),那么它_cannot_从中构建一个`unique_ptr`而不创建双重所有权. (5认同)
  • @mkaes我认为将const引用传递给唯一指针不如在这种情况下传递(可能是cv限定的)原始指针. (2认同)
  • @juanchopanza:我认为使用原始指针总是很难让所有权变得清晰.unique_ptr以一种很好的方式解决了这个问题. (2认同)