C++ 返回智能指针时的最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/974964/
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
best practice when returning smart pointers
提问by Rolle
What is the best practice when returning a smart pointer, for example a boost::shared_ptr? Should I by standard return the smart pointer, or the underlying raw pointer? I come from C# so I tend to always return smart pointers, because it feels right. Like this (skipping const-correctness for shorter code):
返回智能指针(例如 boost::shared_ptr)时的最佳实践是什么?我应该按照标准返回智能指针还是底层原始指针?我来自 C#,所以我倾向于总是返回智能指针,因为它感觉正确。像这样(跳过更短代码的常量正确性):
class X
{
public:
boost::shared_ptr<Y> getInternal() {return m_internal;}
private:
boost::shared_ptr<Y> m_internal;
}
However I've seen some experienced coders returning the raw pointer, and putting the raw pointers in vectors. What is the right way to do it?
但是我看到一些有经验的编码器返回原始指针,并将原始指针放入向量中。正确的做法是什么?
采纳答案by Edouard A.
There is no "right" way. It really depends on the context.
没有“正确”的方式。这真的取决于上下文。
You can internally handle memory with a smart pointer and externally give references or raw pointers. After all, the user of your interface doesn't need to know how you manage memory internally. In a synchronous context this is safe and efficient. In an asynchronous context, there are many pitfalls.
您可以使用智能指针在内部处理内存,并在外部提供引用或原始指针。毕竟,您界面的用户不需要知道您如何在内部管理内存。在同步上下文中,这是安全且高效的。在异步上下文中,存在许多陷阱。
If you're unsure about what to do you can safely return smart pointers to your caller. The object will be deallocated when the references count reaches zero. Just make sure that you don't have a class that keeps smart pointers of objects for ever thus preventing the deallocation when needed.
如果您不确定该做什么,您可以安全地将智能指针返回给您的调用者。当引用计数达到零时,对象将被释放。只要确保您没有一个永远保留对象智能指针的类,从而在需要时防止释放。
As a last note, in C++ don't overuse dynamically allocated objects. There are many cases where you don't need a pointer and can work on references and const references. That's safer and reduces the pressure on the memory allocator.
最后要注意的是,在 C++ 中不要过度使用动态分配的对象。在很多情况下,您不需要指针并且可以处理引用和常量引用。这更安全,并减少了内存分配器的压力。
回答by Todd Gardner
It depends on what the meaning of the pointer is.
这取决于指针的含义。
When returning a shared_pointer, you are syntactically saying "You will share ownership of this object", such that, if the the original container object dies before you release your pointer, that object will still exist.
返回 shared_pointer 时,您在语法上说“您将共享此对象的所有权”,这样,如果原始容器对象在您释放指针之前死亡,则该对象仍将存在。
Returning a raw pointer says: "You know about this object, but don't own it". It's a way of passing control, but not keeping the lifetime tied to the original owner.
返回一个原始指针说:“你知道这个对象,但不拥有它”。这是一种传递控制权的方式,但不会将生命周期与原始所有者联系起来。
(in some older c-programs, it means "It's now your problem to delete me", but I'd heavily recommend avoiding this one)
(在一些较旧的 c 程序中,这意味着“现在删除我是你的问题”,但我强烈建议避免使用这个)
Typically, defaulting to shared saves me a lot of hassle, but it depends on your design.
通常,默认为共享可以为我省去很多麻烦,但这取决于您的设计。
回答by iain
I follow the following guidelines for passing pointers arguments to functions and returning pointers:
我遵循以下准则将指针参数传递给函数并返回指针:
boost::shared_ptr
API and client are sharing ownership of this object. However you have to be careful to avoid circular references with shared_ptr
, if the objects represent some kind of graph. I try to limit my use of shared_ptr
for this reason.
API 和客户端共享此对象的所有权。但是shared_ptr
,如果对象表示某种图形,则必须小心避免使用 循环引用。shared_ptr
由于这个原因,我试图限制我的使用。
boost::weak_ptr / raw pointer
API owns this object, you are allowed share it while it is valid. If there is a chance the client will live longer than the api I use a weak_ptr.
API 拥有此对象,您可以在它有效时共享它。如果客户端有可能比 api 的寿命更长,我会使用weak_ptr。
std::auto_ptr
API is creating an object but the client owns the object. This ensures that the returning code is exception safe, and clearly states that ownership is being transferred.
API 正在创建一个对象,但客户端拥有该对象。这确保返回的代码是异常安全的,并明确说明所有权正在转移。
boost::scoped_ptr
For pointers to objects stored on the stack or as class member variables. I try to use scoped_ptr
first.
用于指向存储在堆栈上或作为类成员变量的对象的指针。我先尝试使用scoped_ptr
。
Like all guidelines there will be times when the rules conflict or have to be bent, then I try to use intelligence.
就像所有的指导方针一样,有时规则会发生冲突或不得不弯曲,然后我尝试使用情报。
回答by Johann Gerell
I typically return "owning"/"unique" smart pointers from factories or similar to make it clear who is responsible for cleaning up.
我通常会从工厂或类似的地方返回“拥有”/“唯一”智能指针,以明确谁负责清理。
This example https://ideone.com/qJnzvashows how to return a std::unique_ptr
that will be deleted when the scope of the variable that the caller assigns the value to goes out of scope.
此示例https://ideone.com/qJnzva显示了如何返回std::unique_ptr
当调用者为其分配值的变量的范围超出范围时将被删除的 。
While it's true that the smart pointer deletes its own pointer, the lifetime of the variable holding the smart pointer is 100% controlled by the caller, so the caller decides when the pointer is deleted. However, since it's a "unique" and "owning" smart pointer, no other client can control the lifetime.
虽然智能指针确实删除了自己的指针,但保存智能指针的变量的生命周期是 100% 由调用者控制的,因此调用者决定何时删除指针。然而,由于它是一个“唯一”和“拥有”的智能指针,没有其他客户端可以控制生命周期。
回答by TimW
I would never return a raw pointer, instead I would return a weak_ptr to tell the user of the pointer that he doesn't have the control over the resource.
我永远不会返回原始指针,而是返回一个 weak_ptr 来告诉指针的用户他没有对资源的控制权。
If you return a weak_ptr its very unlikely that there will be dangling pointers in the application.
如果您返回一个weak_ptr,则应用程序中不太可能存在悬空指针。
If there is a performance problem I would return a reference to the object and a hasValidXObject method.
如果存在性能问题,我将返回对对象的引用和 hasValidXObject 方法。
回答by Oliver N.
In my opinion, in C++, you should always have to justify the use of an unguarded pointer.
在我看来,在 C++ 中,您应该始终证明使用不受保护的指针是合理的。
There could be many valid reasons: a need for very high performance, for very low memory usage, for dealing with legacy libraries, because of some issue with the underlying data structure the pointer is storing. But [dynamically allocated] pointers are somewhat 'evil', in that you have to deallocate the memory at every possible execution path and you will almost certainly forget one.
可能有很多合理的原因:需要非常高的性能,非常低的内存使用量,处理遗留库,因为指针存储的底层数据结构存在一些问题。但是[动态分配的] 指针有点“邪恶”,因为您必须在每个可能的执行路径上释放内存,而且您几乎肯定会忘记一个。
回答by deemok
depends on your goals.
取决于你的目标。
blindly returning smart ptr to internal data might not be a good idea (which is very sensitive to the task you're trying to solve) - you might be better off just offering some doX() and doY() that use the pointer internally instead.
盲目地将智能 ptr 返回到内部数据可能不是一个好主意(这对您要解决的任务非常敏感)-您最好提供一些在内部使用指针的 doX() 和 doY() 来代替.
on the other hand, if returning the smart ptr, you should also consider that you'll create no mutual circular references when objects end up unable to destroy each other (weak_ptr might be a better option in that case).
另一方面,如果返回智能 ptr,您还应该考虑到当对象最终无法相互销毁时,您将不会创建相互循环引用(在这种情况下,weak_ptr 可能是更好的选择)。
otherwise, like already mentioned above, performance/legacy code/lifetime considerations should all be taken into account.
否则,就像上面已经提到的,性能/遗留代码/生命周期的考虑都应该被考虑在内。
回答by Beno?t
I wouldn't put raw pointers in vectors.
我不会将原始指针放在向量中。
In case they use auto_ptr or boost::scoped_ptr, they can't use (or return) anything but raw pointers. That could explain their way of coding, i guess.
如果他们使用 auto_ptr 或 boost::scoped_ptr,他们不能使用(或返回)除了原始指针之外的任何东西。我想这可以解释他们的编码方式。
回答by chila
const boost::shared_ptr &getInternal() {return m_internal;}
const boost::shared_ptr &getInternal() {return m_internal;}
This avoids a copy.
这避免了复制。
Sometimes you'll like to return a reference, for example:
有时你会想要返回一个引用,例如:
- Y &operator*() { return *m_internal; }
- const Y &operator*() const { return *m_internal; }
- Y &operator*() { return *m_internal; }
- const Y &operator*() const { return *m_internal; }
This is good too only if the reference will be used and discarded inmediately. The same goes for a raw pointer. Returning a weak_ptr is also an option.
仅当引用将被立即使用和丢弃时,这也很好。原始指针也是如此。返回一个 weak_ptr 也是一种选择。
The 4 are good depending on the goals. This question requires a more extensive discussion.
根据目标,这4个是好的。这个问题需要更广泛的讨论。