C++ 将 unique_ptr 传递给函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9699333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing unique_ptr to functions
提问by jcoder
I'm trying to "modernize" some existing code.
我正在尝试“现代化”一些现有代码。
- I have a class which currently has a member variable "Device* device_".
- It uses new to create an instance in some initialization code and has a "delete device_" in the destructory.
- Member functions of this class call manyother functions that take a Device* as a parameter.
- 我有一个当前具有成员变量“Device* device_”的类。
- 它在一些初始化代码中使用 new 创建一个实例,并在析构函数中有一个“删除设备_”。
- 此类的成员函数调用了许多其他以 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?
- 我应该如何再通过设备_变量都需要它作为一个paramater的功能呢?
I can call .get to get the raw pointer in each function call. But that seems ugly and wastes some of the reasons to use a unique_ptr in the first place.
我可以调用 .get 来获取每个函数调用中的原始指针。但这看起来很丑陋,并且浪费了一些首先使用 unique_ptr 的理由。
Or I can change everyfunction so that instead of taking a parameter of type "Device*" it now takes a paramater of type "std::unique_ptr& ". Which (to me) somewhat obfuscates the function prototypes, and makes them hard to read.
或者,我可以更改每个函数,而不是采用“Device*”类型的参数,它现在采用“std::unique_ptr&”类型的参数。这(对我来说)有点混淆了函数原型,并使它们难以阅读。
What is best practice for this? Have I missed any other options?
什么是最佳实践?我错过了其他选择吗?
采纳答案by Matthieu M.
In ModernC++ style, there are two keys concepts:
在现代C++ 风格中,有两个关键概念:
- Ownership
- Nullity
- 所有权
- 无效
Ownershipis about the owner of some object/resource (in this case, an instance of Device
). The various std::unique_ptr
, boost::scoped_ptr
or std::shared_ptr
are about ownership.
所有权是关于某些对象/资源的所有者(在本例中,是 的实例Device
)。各种各样的std::unique_ptr
,boost::scoped_ptr
或者std::shared_ptr
是关于所有权的。
Nullityis 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!
无效更加简单不过:它只是表达了一种给定的对象是否可能为空,并且不关心别的,肯定不是所有权!
You were rightto 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 usersof 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 上有一个陷阱)
回答by juanchopanza
It really depends. If a function must take ownership of the unique_ptr, then it's signature should take a unique_ptr<Device>
bv valueand the caller should std::move
the pointer. If ownership is not an issue, then I would keep the raw pointer signature and pass the pointer unique_ptr using get()
. This isn't ugly ifthe function in question does not take over ownership.
这真的取决于。如果一个函数必须拥有 unique_ptr 的所有权,那么它的签名应该采用unique_ptr<Device>
bv值,调用者应该std::move
采用指针。如果所有权不是问题,那么我将保留原始指针签名并使用get()
. 如果相关功能不接管所有权,这并不难看。
回答by mkaes
I would use std::unique_ptr const&
. Using a non const reference will give the called function the possibility to reset your pointer.
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.
我会使用std::unique_ptr const&
. 使用非 const 引用将使被调用函数有可能重置您的指针。
我认为这是表达被调用函数可以使用指针而不是其他任何东西的好方法。
所以对我来说,这将使界面更易于阅读。我知道我不必摆弄传递给我的指针。
回答by James Kanze
The best practice is probably not to use std::unique_ptr
in this case,
although it depends. (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). 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. 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).
最佳做法可能是std::unique_ptr
在这种情况下不使用,尽管这取决于情况。(您通常不应该在一个类中拥有多个指向动态分配对象的原始指针。尽管这也取决于。)在这种情况下,您不想做的一件事是传递std::unique_ptr
(正如您所注意到的) ,
std::unique_ptr<> const&
有点笨拙和混淆)。如果这是对象中唯一动态分配的指针,我会坚持使用原始指针,并delete
在析构函数中使用。如果有几个这样的指针,我会考虑将它们中的每一个都降级到一个单独的基类(它们仍然可以是原始指针)。
回答by J.N.
That may be not feasible for you but a replacing every occurence of Device*
by const unique_ptr<Device>&
is a good start.
这对您来说可能不可行,但替换每次出现的Device*
byconst unique_ptr<Device>&
是一个好的开始。
You obviously can't copy unique_ptr
s and you don't want to move it. Replacing by a reference to unique_ptr
allows the body of the existing functions' bodies to keep on working.
你显然不能复制unique_ptr
s 并且你不想移动它。替换为引用unique_ptr
允许现有函数的主体继续工作。
Now there's a trap, you must pass by const &
to prevent callees from doing unique_ptr.reset()
or 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 &
以防止被调用者执行unique_ptr.reset()
or unique_ptr().release()
。请注意,这仍然将可修改的指针传递给设备。使用此解决方案,您无法轻松地将指针或引用传递给const Device
.