C++ 提升,共享ptr与弱ptr?什么时候用哪个?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2036182/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:54:28  来源:igfitidea点击:

boost, shared ptr Vs weak ptr? Which to use when?

c++memory-managementboostshared-ptrweak-ptr

提问by RLT

In my current project I am using boost::shared_ptrquite extensively.

在我当前的项目中,我使用的boost::shared_ptr非常广泛。

Recently my fellow team mates have also started using weak_ptr. I don't know which one to use and when.

最近我的队友也开始使用weak_ptr. 我不知道该使用哪一种以及何时使用。

Apart from this, what should I do if I want to convert weak_ptrto shared_ptr. Does putting a lock on weak_ptrto create a shared_ptraffect my code in other thread?

除此之外,如果我想转换weak_ptrshared_ptr. 难道把一个锁weak_ptr创建一个shared_ptr影响我在其他线程的代码?

回答by Narfanator

In general and summary,

总的来说,总结一下,

Strong pointersguarantee their own validity. Use them, for example, when:

强指针保证其自身的有效性。例如,在以下情况下使用它们:

  • You own the object being pointed at; you create it and destroy it
  • You do not have defined behavior if the object doesn't exist
  • You need to enforce that the object exists.
  • 你拥有被指向的对象;你创造它并摧毁它
  • 如果对象不存在,则您没有定义的行为
  • 您需要强制对象存在。

Weak pointersguarantee knowingtheir own validity. Use them, for example, when:

弱指针保证知道自己的有效性。例如,在以下情况下使用它们:

  • You access it, but it's not yours.
  • You have defined behavior if the object doesn't exist
  • 您可以访问它,但它不是您的。
  • 如果对象不存在,则您已定义行为

Lock() on a weak pointer returns a strong pointer; this is how you access the weak pointer. If the object is no longer valid (it's been deleted, etc), then the strong pointer will be NULL, otherwise, it will point at the object. You will need to check this.

弱指针上的 Lock() 返回强指针;这就是您访问弱指针的方式。如果对象不再有效(它已被删除等),则强指针将为 NULL,否则,它将指向该对象。你需要检查一下。

It's set up this way so that you cannot accidentally delete the object while you're using it, because you've made a temporary (local) strong pointer, and thus garunteed the object's existence while that strong pointer remains. When you're done using the object, you generally let the strong pointer fall out of scope (or reassigning it), which then allows the object to be deleted. For multithreading, treat them with same care you treat other things that don't have built-in thread safety, noting that the guarantee I mentioned above willhold when multithreading. AFAIK they don't do anything special past that.

它是这样设置的,这样您就不会在使用对象时意外删除它,因为您已经创建了一个临时(本地)强指针,从而在该强指针保留的同时保证了对象的存在。当您使用完对象后,通常会让强指针超出范围(或重新分配它),然后允许删除该对象。对于多线程,对待它们与对待其他没有内置线程安全的事物一样小心,注意我上面提到的保证在多线程时保持不变。AFAIK 他们没有做任何特别的事情。

The boost shared pointers also have garbage-collector like features, since when the last strong pointer to an object goes away or points somewhere else, the object gets deleted.

boost 共享指针还具有类似垃圾收集器的功能,因为当指向对象的最后一个强指针消失或指向其他地方时,该对象将被删除。

There's also the performance and circular dependencies mentioned in the other answers.

还有其他答案中提到的性能和循环依赖。

Fundamentally, I would say that the boost shared pointer library allows you to not mess up putting together a program, but it is no substitute for taking the time to properly design your pointers, object ownerships and lifetimes. If you have such a design, you can use the library to enforce it. If you don't have such a design, you're likely to run into different problems than before.

从根本上说,boost 共享指针库可以让您不会把程序放在一起,但它不能替代花时间正确设计您的指针、对象所有权和生命周期。如果你有这样的设计,你可以使用库来强制执行它。如果您没有这样的设计,您可能会遇到与以前不同的问题。

回答by blwy10

Use weak_ptrwhen the objects you create contain cyclical references, i.e. shared_ptrto an object with a shared_ptrback to yourself. This is because shared_ptrcannot handle cyclical references - when both objects go out of scope, the mutual referencing means that they are not "garbage collected", so the memory is lost and you have a memory leak. Since weak_ptrdoes not increase the reference count, the cyclical reference problem does not occur. This also means in general that if you just want to take a pointer to something that is reference counted and do not want to increase its reference count, then use weak_ptr.

使用weak_ptr在创建对象包含循环引用,即shared_ptr一个对象与shared_ptr回自己。这是因为shared_ptr无法处理循环引用——当两个对象都超出范围时,相互引用意味着它们没有被“垃圾收集”,因此内存丢失并且内存泄漏。由于weak_ptr不增加引用计数,所以不会出现循环引用问题。这也意味着一般来说,如果您只想获取指向引用计数的内容的指针并且不想增加其引用计数,则使用weak_ptr.

Otherwise, you can use shared_ptr.

否则,您可以使用shared_ptr.

For more information, check the Boost documentation.

有关更多信息,请查看 Boost文档

回答by Antti Huima

Shared pointers implement reference counting, weak pointers do not affect reference counting and if you don't have shared pointers to an object, only weak pointers, the object gets deleted and the weak pointers now tell you that the object has been lost.

共享指针实现引用计数,弱指针不影响引用计数,如果你没有指向对象的共享指针,只有弱指针,对象被删除,弱指针现在告诉你对象已经丢失。

There are two reasons to use a weak pointer:

使用弱指针有两个原因:

  1. To eliminate the cost of reference count increase / decrease; however you shouldn't do this because it is error-prone and doesn't really save much time
  2. In bookkeeping data structures, e.g. you have an index of all objects Foo that are "alive", i.e. used somewhere else, and you don't want to keep a Foo alive in the index if all the "real" uses have ended. This is the basic realistic use case for weak pointers. Of course others exist also.
  1. 消除引用计数增加/减少的成本;但是你不应该这样做,因为它容易出错并且并没有真正节省多少时间
  2. 在簿记数据结构中,例如,您拥有所有“活动”对象 Foo 的索引,即在其他地方使用,并且如果所有“实际”使用都结束了,您不希望在索引中保持 Foo 活动。这是弱指针的基本现实用例。当然其他的也存在。

So in general, my recommendation would be to use weak pointers only when you know that you want to let the referenced objects be deleted and want to detect that. In other cases use shared pointers (reference counting), or direct pointers, esp. in method local variables when you know that the objects are not going to get deleted. Also errorprone, though, but faster than shared pointers.

所以总的来说,我的建议是仅当您知道要删除引用的对象并希望检测到它时才使用弱指针。在其他情况下,使用共享指针(引用计数)或直接指针,尤其是。当您知道对象不会被删除时,在方法局部变量中。虽然也容易出错,但比共享指针快。

N.B. cyclical objects do not need weak pointers, you can use non-cooked, regular pointers instead in most properly constructed programs. Weak pointers less risky, though.

NB 循环对象不需要弱指针,您可以在大多数正确构造的程序中使用未煮熟的常规指针。不过,弱指针风险较小。

回答by Charles Eli Cheese

You should probably not be trying to use weak pointers at all unless you are trying to implement a garbage collector, which is not a hot idea in C++ because it's too hard to keep track of everything that could go wrong closely enough.

除非您尝试实现垃圾收集器,否则您可能根本不应该尝试使用弱指针,这在 C++ 中不是一个热门想法,因为很难跟踪所有可能出错的地方。