智能指针。何时,何地以及如何?

时间:2023-01-05 21:17:50

First off, since there are different kinds of smart pointers, I'd like to focus this question on two of them: reference counted intrusive and non-intrusive smart pointers. The question is asked individualy for each pointer type.

首先,由于存在不同类型的智能指针,我想将这个问题集中在其中两个上:引用计入侵入式和非侵入式智能指针。针对每种指针类型单独询问该问题。

I am not really sure how to formulate my question, so here's what I'm not asking: I am not asking why, or when, are smart pointers needed. Neither which type of smart pointer should I use and for what.

我不确定如何制定我的问题,所以这就是我不问的问题:我不是在问为什么或什么时候需要智能指针。我不应该使用哪种类型的智能指针。

Here is what I'm asking, and I hope it's clear enough: When dealing with "smartly-managed" objects, in which contextes should I use which pointer semantics? That is, smart pointer semantics, raw pointer semantics, something else (Such as a reference to a smart pointer)?

这就是我所要求的,我希望它足够清楚:当处理“智能管理”对象时,我应该在哪些上下文中使用哪个指针语义?也就是说,智能指针语义,原始指针语义,别的东西(比如对智能指针的引用)?

It's preety obvious that when I "store" a pointer to an object (object being a reference counted memory entity), such as a global pointer, or as a class member, it should be a smart pointer, so it would claim ownership, but what about other situations?

显而易见的是,当我“存储”指向对象的指针(对象是引用计数的内存实体)时,例如全局指针,或者作为类成员,它应该是一个智能指针,因此它会声称所有权,但是其他情况怎么样?

When I'm passing a pointer as a function argument, should it be a smart-pointer, a raw pointer, a reference to a smart pointer, or maybe something else? What about returned pointers? Local pointers? so on...

当我将指针作为函数参数传递时,它应该是智能指针,原始指针,对智能指针的引用,还是其他什么?返回指针怎么样?本地指针?等......

Ofcourse, I could use smart pointers everywhere, which is the safest option, but I am feeling that this is really unnecessary and adds overhead.

当然,我可以在任何地方使用智能指针,这是最安全的选择,但我觉得这实际上是不必要的并增加了开销。

7 个解决方案

#1


IMHO, sometimes it's better to do things faster than to have a minor performance improvement. I'm supposing you will do things faster if you always use smart pointers.

恕我直言,有时候做事更快,而不是稍微提高绩效。如果你总是使用智能指针,我想你会更快地做事。

My suggestion: Use smart pointers everywhere. Then use a profiler to see if it generates considerable overhead. Where it does, change it :)

我的建议:到处使用智能指针。然后使用分析器查看它是否会产生相当大的开销。它在哪里,改变它:)

#2


I suggest you limit the use of pointers, smart or otherwise, as much as possible. I don't know your background, but many people coming from languages like Java or C# use pointers when they should be really using values and call by reference. Use of pointers in a C++ program should be relatively rare.

我建议你尽可能地限制智能或其他指针的使用。我不知道你的背景,但很多人来自Java或C#等语言,他们应该真正使用值并通过引用调用。在C ++程序中使用指针应该相对较少。

#3


If you are tyring to contrast "smart pointer semantics" and "raw pointer semantics", you are incorrectly assuming that you can group all "smart pointer semantics" together. I disagree. The difference between boost::scoped_ptr and boost::shared_ptr is of the same order of magnitude as the difference bwteeen boost::shared_ptr and T*

如果您想要对比“智能指针语义”和“原始指针语义”,那么您错误地认为可以将所有“智能指针语义”组合在一起。我不同意。 boost :: scoped_ptr和boost :: shared_ptr之间的区别与bwteeen boost :: shared_ptr和T *的差异相同。

When you "store" a pointer to an object as a class member, you haven't really said a lot about the semantics. If the referenced object is logically a member ("owned"), then yes, you'd want a smart pointer. But one with very specific semantics: single ownership. This means no shared ownership, nor a weak pointer, to name two other common smart pointers. On the other hand, if you're storing a pointer to a error logging object, you probably want a weak pointer. This will prevent you from crashing during shutdown - the weak pointer will be NULL if the log is gone.

当您将指向对象的指针“存储”为类成员时,您并没有真正说过很多关于语义的内容。如果引用的对象在逻辑上是一个成员(“拥有”),那么是的,你需要一个智能指针。但是具有非常特定的语义:单一所有权。这意味着没有共享所有权,也没有弱指针来命名其他两个常见的智能指针。另一方面,如果您存储指向错误记录对象的指针,则可能需要弱指针。这将防止您在关机期间崩溃 - 如果日志消失,弱指针将为NULL。

Similarly, when you're returning a pointer from a function, the actual semantics of the case will dictate the type of pointer you need. Not the simple fact that it's returned from a function.

类似地,当您从函数返回指针时,案例的实际语义将决定您需要的指针类型。它不是从函数返回的简单事实。

#4


My list of pointers:

我的指针列表:

  • normal usage: normal members and (const) references to them
  • 正常用法:普通成员和(const)对它们的引用

  • sharing and keeping the object alive (owners, containers): shared_ptr
  • 共享和保持对象存活(所有者,容器):shared_ptr

  • sharing, but not keeping alive (users): weak_ptr
  • 分享,但没有保持活力(用户):weak_ptr

  • scoped usage: scoped_ptr
  • 范围用法:scoped_ptr

  • other usages (output-parameter,...): raw pointer
  • 其他用法(output-parameter,...):原始指针

#5


In many situations, the use of smart pointers relate to memory management and/or exception handling. The STL auto_ptr neatly manage destruction even in complex try/catch environment. Smart pointers are useful to delegate the lifecycle of the pointed object to the smart pointer. It is generally needed whenever it is difficult to follow the paradigm "destroy your object where you have created it". A reference type smart pointer can be useful when you cannot easily manage a shared object. I prefer to solve this sort of problem with a good architecture, but there is cases where smart pointers are the best way.

在许多情况下,智能指针的使用涉及内存管理和/或异常处理。即使在复杂的try / catch环境中,STL auto_ptr也能整齐地管理破坏。智能指针可用于将指向对象的生命周期委派给智能指针。只要难以遵循范式“摧毁你创造它的对象”,通常就需要它。当您无法轻松管理共享对象时,引用类型智能指针非常有用。我更喜欢用一个好的架构来解决这类问题,但有些情况下智能指针是最好的方法。

#6


In my experience, when I'm passing the object to a function that doesn't need to store a reference to the object (or otherwise, that calling the function does not affect the lifetime of the object in any way), then it's safe to pass the object by reference. This makes the code less "tied" to the smart pointer type.

根据我的经验,当我将对象传递给不需要存储对象引用的函数时(否则,调用函数不会以任何方式影响对象的生命周期),那么它是安全的通过引用传递对象。这使代码与智能指针类型“联系”。

On the other hand, always using the smart pointer type is "always safe", so when in doubt....

另一方面,总是使用智能指针类型是“永远安全”,所以当有疑问....

#7


"When I'm passing a pointer as a function argument, should it be a smart-pointer, a raw
pointer, a reference to a smart pointer, or maybe something else? What about returned
pointers? Local pointe rs? so on..."

my 2p, unless you have an obvious reason to use shared_ptrs don't:

我的2p,除非你有明显的理由使用shared_ptrs不:

Don't pass pointers to functions, pass references to the objects

不要将指针传递给函数,将引用传递给对象

Don't return pointers from functions, pass objects as non-const references and change those objects

不要从函数返回指针,将对象作为非const引用传递并更改这些对象

When creating local objects on the heap use scoped_ptr

在堆上创建本地对象时,请使用scoped_ptr

#1


IMHO, sometimes it's better to do things faster than to have a minor performance improvement. I'm supposing you will do things faster if you always use smart pointers.

恕我直言,有时候做事更快,而不是稍微提高绩效。如果你总是使用智能指针,我想你会更快地做事。

My suggestion: Use smart pointers everywhere. Then use a profiler to see if it generates considerable overhead. Where it does, change it :)

我的建议:到处使用智能指针。然后使用分析器查看它是否会产生相当大的开销。它在哪里,改变它:)

#2


I suggest you limit the use of pointers, smart or otherwise, as much as possible. I don't know your background, but many people coming from languages like Java or C# use pointers when they should be really using values and call by reference. Use of pointers in a C++ program should be relatively rare.

我建议你尽可能地限制智能或其他指针的使用。我不知道你的背景,但很多人来自Java或C#等语言,他们应该真正使用值并通过引用调用。在C ++程序中使用指针应该相对较少。

#3


If you are tyring to contrast "smart pointer semantics" and "raw pointer semantics", you are incorrectly assuming that you can group all "smart pointer semantics" together. I disagree. The difference between boost::scoped_ptr and boost::shared_ptr is of the same order of magnitude as the difference bwteeen boost::shared_ptr and T*

如果您想要对比“智能指针语义”和“原始指针语义”,那么您错误地认为可以将所有“智能指针语义”组合在一起。我不同意。 boost :: scoped_ptr和boost :: shared_ptr之间的区别与bwteeen boost :: shared_ptr和T *的差异相同。

When you "store" a pointer to an object as a class member, you haven't really said a lot about the semantics. If the referenced object is logically a member ("owned"), then yes, you'd want a smart pointer. But one with very specific semantics: single ownership. This means no shared ownership, nor a weak pointer, to name two other common smart pointers. On the other hand, if you're storing a pointer to a error logging object, you probably want a weak pointer. This will prevent you from crashing during shutdown - the weak pointer will be NULL if the log is gone.

当您将指向对象的指针“存储”为类成员时,您并没有真正说过很多关于语义的内容。如果引用的对象在逻辑上是一个成员(“拥有”),那么是的,你需要一个智能指针。但是具有非常特定的语义:单一所有权。这意味着没有共享所有权,也没有弱指针来命名其他两个常见的智能指针。另一方面,如果您存储指向错误记录对象的指针,则可能需要弱指针。这将防止您在关机期间崩溃 - 如果日志消失,弱指针将为NULL。

Similarly, when you're returning a pointer from a function, the actual semantics of the case will dictate the type of pointer you need. Not the simple fact that it's returned from a function.

类似地,当您从函数返回指针时,案例的实际语义将决定您需要的指针类型。它不是从函数返回的简单事实。

#4


My list of pointers:

我的指针列表:

  • normal usage: normal members and (const) references to them
  • 正常用法:普通成员和(const)对它们的引用

  • sharing and keeping the object alive (owners, containers): shared_ptr
  • 共享和保持对象存活(所有者,容器):shared_ptr

  • sharing, but not keeping alive (users): weak_ptr
  • 分享,但没有保持活力(用户):weak_ptr

  • scoped usage: scoped_ptr
  • 范围用法:scoped_ptr

  • other usages (output-parameter,...): raw pointer
  • 其他用法(output-parameter,...):原始指针

#5


In many situations, the use of smart pointers relate to memory management and/or exception handling. The STL auto_ptr neatly manage destruction even in complex try/catch environment. Smart pointers are useful to delegate the lifecycle of the pointed object to the smart pointer. It is generally needed whenever it is difficult to follow the paradigm "destroy your object where you have created it". A reference type smart pointer can be useful when you cannot easily manage a shared object. I prefer to solve this sort of problem with a good architecture, but there is cases where smart pointers are the best way.

在许多情况下,智能指针的使用涉及内存管理和/或异常处理。即使在复杂的try / catch环境中,STL auto_ptr也能整齐地管理破坏。智能指针可用于将指向对象的生命周期委派给智能指针。只要难以遵循范式“摧毁你创造它的对象”,通常就需要它。当您无法轻松管理共享对象时,引用类型智能指针非常有用。我更喜欢用一个好的架构来解决这类问题,但有些情况下智能指针是最好的方法。

#6


In my experience, when I'm passing the object to a function that doesn't need to store a reference to the object (or otherwise, that calling the function does not affect the lifetime of the object in any way), then it's safe to pass the object by reference. This makes the code less "tied" to the smart pointer type.

根据我的经验,当我将对象传递给不需要存储对象引用的函数时(否则,调用函数不会以任何方式影响对象的生命周期),那么它是安全的通过引用传递对象。这使代码与智能指针类型“联系”。

On the other hand, always using the smart pointer type is "always safe", so when in doubt....

另一方面,总是使用智能指针类型是“永远安全”,所以当有疑问....

#7


"When I'm passing a pointer as a function argument, should it be a smart-pointer, a raw
pointer, a reference to a smart pointer, or maybe something else? What about returned
pointers? Local pointe rs? so on..."

my 2p, unless you have an obvious reason to use shared_ptrs don't:

我的2p,除非你有明显的理由使用shared_ptrs不:

Don't pass pointers to functions, pass references to the objects

不要将指针传递给函数,将引用传递给对象

Don't return pointers from functions, pass objects as non-const references and change those objects

不要从函数返回指针,将对象作为非const引用传递并更改这些对象

When creating local objects on the heap use scoped_ptr

在堆上创建本地对象时,请使用scoped_ptr