我正试图“现代化”一些现有的代码。
这很好用,但为了“现代化”我的代码,我认为我应该将变量定义为"std::unique_ptr<Device> device_"
并删除显式调用delete,这样可以使代码更安全,通常更好。
我的问题是这个 -
我可以调用.get来获取每个函数调用中的原始指针。但这看起来很难看,并且浪费了一些使用unique_ptr的原因。
或者我可以更改每个函数,以便不使用“Device *”类型的参数,而是使用“std :: unique_ptr&amp;”类型的参数。哪个(对我来说)有点模糊了函数原型,并使它们难以阅读。
这是什么最佳做法?我错过了其他任何选择吗?
答案 0 :(得分:44)
在 Modern C ++风格中,有两个关键概念:
所有权是关于某个对象/资源的所有者(在这种情况下,是Device
的实例)。各种std::unique_ptr
,boost::scoped_ptr
或std::shared_ptr
都与所有权有关。
Nullity 更简单:它只是表达给定对象是否为空,并且不关心任何其他内容,当然也不关心所有权!
你正确将类的实现移向unique_ptr
(一般情况下),但如果您的目标是实现PIMPL,您可能需要具有深层复制语义的智能指针
这清楚地表明,你的班级是唯一负责这段记忆的人,并且整齐地处理了记忆本可以泄露的各种方式。
另一方面,资源的大多数用户对其所有权的关注度不高。
只要函数不保留对对象的引用(将其存储在地图或其他内容中),那么重要的是对象的生命周期超过函数调用的持续时间。
因此,选择如何传递参数取决于其可能的 Nullity :
答案 1 :(得分:14)
这取决于。如果某个函数必须取得unique_ptr的所有权,那么它的签名应该采用unique_ptr<Device>
bv 值,并且调用者应该std::move
指针。如果所有权不是问题,那么我将保留原始指针签名并使用get()
传递指针unique_ptr。这不是丑陋如果有问题的功能没有接管所有权。
答案 2 :(得分:7)
我会使用std::unique_ptr const&
。使用非const引用将为被调用函数提供重置指针的可能性
我认为这是表达被调用函数可以使用指针而不是其他任何东西的好方法
所以对我来说这将使界面更容易阅读。我知道我不必乱用指针传给我。
答案 3 :(得分:2)
在这种情况下,最佳做法可能不是std::unique_ptr
,
虽然这取决于。 (你通常不应该有一个以上的原始
指向类中动态分配的对象的指针。虽然这个
也取决于。)在这种情况下你不想做的一件事是
绕过std::unique_ptr
(正如你所注意到的,
std::unique_ptr<> const&
有点笨拙和混淆)。如果这
是对象中唯一动态分配的指针,我只是坚持
使用原始指针和析构函数中的delete
。如果有
几个这样的指针,我考虑将每个指针降级到一个
单独的基类(它们仍然可以是原始指针)。
答案 4 :(得分:1)
这对您来说可能不太可行,但Device*
const unique_ptr<Device>&
的所有出现都是一个良好的开端。
你显然无法复制unique_ptr
并且你不想移动它。通过引用unique_ptr
替换允许现有函数体的主体继续工作。
现在有一个陷阱,您必须经过const &
以阻止被访问者unique_ptr.reset()
或unique_ptr().release()
。请注意,这仍然会将可修改的指针传递给设备。使用此解决方案,您无法轻松地将指针或引用传递给const Device
。