简体   繁体   English

将unique_ptr传递给函数

[英]Passing unique_ptr to functions

I'm trying to "modernize" some existing code. 我正试图“现代化”一些现有的代码。

  • I have a class which currently has a member variable "Device* device_". 我有一个类,当前有一个成员变量“Device * device_”。
  • It uses new to create an instance in some initialization code and has a "delete device_" in the destructory. 它使用new在一些初始化代码中创建一个实例,并在destructory中有一个“delete device_”。
  • Member functions of this class call many other functions that take a Device* as a parameter. 此类的成员函数调用许多其他函数,这些函数将Device *作为参数。

This works well, but to "modernize" my code I thought I ought to change the variable to be defined as "std::unique_ptr<Device> device_" and remove the explicit call to delete, which makes the code safer and generally better. 这很好用,但为了“现代化”我的代码,我认为我应该将变量定义为"std::unique_ptr<Device> device_"并删除显式调用delete,这样可以使代码更安全,通常更好。

My question is this - 我的问题是这个 -

  • How should I then pass the device _ variable to all of the functions that need it as a paramater? 那么我应该如何将device _变量传递给需要它作为参数的所有函数?

I can call .get to get the raw pointer in each function call. 我可以调用.get来获取每个函数调用中的原始指针。 But that seems ugly and wastes some of the reasons to use a unique_ptr in the first place. 但这看起来很丑陋,浪费了一些首先使用unique_ptr的原因。

Or I can change every function so that instead of taking a parameter of type "Device*" it now takes a paramater of type "std::unique_ptr& ". 或者我可以更改每个函数,以便不使用“Device *”类型的参数,而是使用“std :: unique_ptr&”类型的参数。 Which (to me) somewhat obfuscates the function prototypes, and makes them hard to read. 哪个(对我来说)有点模糊了函数原型,并使它们难以阅读。

What is best practice for this? 这是什么最佳做法? Have I missed any other options? 我错过了其他选择吗?

In Modern C++ style, there are two keys concepts: Modern C ++风格中,有两个关键概念:

  • Ownership 所有权
  • Nullity 婚姻无效

Ownership is about the owner of some object/resource (in this case, an instance of Device ). 所有权是关于某个对象/资源的所有者(在这种情况下,是Device的实例)。 The various std::unique_ptr , boost::scoped_ptr or std::shared_ptr are about ownership. 各种std::unique_ptrboost::scoped_ptrstd::shared_ptr是关于所有权的。

Nullity is much more simple however: it just expresses whether or not a given object might be null, and does not care about anything else, and certainly not about ownership! 然而, Nullity更简单:它只是表达给定对象是否为null,并且不关心任何其他内容,当然也不关心所有权!


You were right to move the implementation of your class toward unique_ptr (in general), though you may want a smart pointer with deep copy semantics if your goal is to implement a PIMPL. 你是移动类的朝实施unique_ptr (一般),虽然你可能想与深拷贝语义的智能指针如果你的目标是实现一个PIMPL。

This clearly conveys that your class is the sole responsible for this piece of memory and neatly deals with all the various ways memory could have leaked otherwise. 这清楚地表明,你的班级是唯一负责这段记忆的人,并且巧妙地处理了记忆本可以泄露的各种方式。


On the other hand, most users of the resources could not care less about its ownership. 另一方面,资源的大多数用户对其所有权不太关心。

As long as a function does not keep a reference to an object (store it in a map or something), then all that matters is that the lifetime of the object exceeds the duration of the function call. 只要函数不保持对对象的引用(将其存储在映射或其他内容中),那么重要的是对象的生命周期超过函数调用的持续时间。

Thus, choosing how to pass the parameter depends on its possible Nullity : 因此,选择如何传递参数取决于其可能的Nullity

  • Never null? 永远不会? Pass a reference 传递参考
  • Possibly null? 可能是空的? Pass a pointer , a simple bare pointer or a pointer-like class (with a trap on null for example) 传递一个指针 ,一个简单的裸指针或类似指针的类(例如,在null上有一个陷阱)

It really depends. 这真的取决于。 If a function must take ownership of the unique_ptr, then it's signature should take a unique_ptr<Device> bv value and the caller should std::move the pointer. 如果函数必须取得unique_ptr的所有权,那么它的签名应该采用unique_ptr<Device> bv ,并且调用者应该std::move指针。 If ownership is not an issue, then I would keep the raw pointer signature and pass the pointer unique_ptr using get() . 如果所有权不是问题,那么我将保留原始指针签名并使用get()传递指针unique_ptr。 This isn't ugly if the function in question does not take over ownership. 如果有问题的功能不接管所有权,这并不难看。

I would use std::unique_ptr const& . 我会使用std::unique_ptr const& Using a non const reference will give the called function the possibility to reset your pointer. 使用非const引用将为被调用函数提供重置指针的可能性。
I think this is a nice way to express that your called function can use the pointer but nothing else. 我认为这是表达被调用函数可以使用指针而不是其他任何东西的好方法。
So for me this will make the interface easier to read. 所以对我来说这将使界面更容易阅读。 I know that I don't have to fiddle around with pointer passed to me. 我知道我不必乱用指针传给我。

The best practice is probably not to use std::unique_ptr in this case, although it depends. 在这种情况下,最好的做法可能不是使用std::unique_ptr ,尽管它取决于。 (You generally should not have more than one raw pointer to a dynamically allocated object in a class. Although this also depends.) The one thing you don't want to be doing in this case is passing around std::unique_ptr (and as you've noticed, std::unique_ptr<> const& is a bit unwieldy and obfuscating). (通常不应该有一个指向类中动态分配对象的原始指针。虽然这也取决于。)在这种情况下你不想做的一件事就是传递std::unique_ptr (和你注意到了, std::unique_ptr<> const&有点笨拙和混淆)。 If this is the only dynamically allocated pointer in the object, I'd just stick with the raw pointer, and the delete in the destructor. 如果这是对象中唯一动态分配的指针,我只会坚持使用原始指针和析构函数中的delete If there are several such pointers, I'd consider relegating each of them to a separate base class (where they can still be raw pointers). 如果有几个这样的指针,我会考虑将它们中的每一个降级到一个单独的基类(它们仍然可以是原始指针)。

That may be not feasible for you but a replacing every occurence of Device* by const unique_ptr<Device>& is a good start. 这对你来说可能不太可行,但是通过const unique_ptr<Device>&取代Device*的每一次出现都是一个好的开始。

You obviously can't copy unique_ptr s and you don't want to move it. 您显然无法复制unique_ptr并且您不想移动它。 Replacing by a reference to unique_ptr allows the body of the existing functions' bodies to keep on working. 通过引用unique_ptr替换允许现有函数体的主体继续工作。

Now there's a trap, you must pass by const & to prevent callees from doing unique_ptr.reset() or unique_ptr().release() . 现在有一个陷阱,你必须传递const &以防止被调用者执行unique_ptr.reset()unique_ptr().release() Note that this still passes a modifiable pointer to device. 请注意,这仍然会将可修改的指针传递给设备。 With this solution you have no easy way to pass a pointer or reference to a const Device . 使用此解决方案,您无法轻松地将指针或引用传递给const Device

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM