传递给方法时,我应该将shared_ptr转换为weak_ptr吗?

时间:2011-03-23 15:57:10

标签: c++ shared-ptr

关于此主题已经有几个问题,但我仍然不确定该怎么做:我们的代码库在很多地方使用shared_ptr。我必须承认,在编写时我们没有明确定义所有权。

我们有一些方法,比如

 void doSomething(shared_ptr<MyClass> ptr)
 {
      //doSomething() is a member function of a class, but usually won't store the ptr
      ptr->foo();
      ...
 }

在发现第一个(间接)循环依赖关系之后,我想纠正我们设计中的错误。但我不确定如何。将方法从上面改为

有什么好处
 void doSomething(weak_ptr<MyClass> ptr)
 {
      shared_ptr<MyClass> ptrShared = ptr.lock();
      ptrShared->foo();
      ...
 }

我也很困惑,因为有些人说(包括谷歌风格指南)首先要确保所有权的正确性(这可能意味着引入了许多weak_ptrs,例如在方法的例子中上面,但也有我们的许多成员变量)。其他人说(请参阅下面的链接)你应该使用weak_ptr来打破循环依赖。但是,检测它们并不总是很容易,所以我想我是否真的应该使用shared_ptr,直到我遇到问题(并实现它们),然后修复它们?

感谢您的想法!

另见

4 个答案:

答案 0 :(得分:6)

  

我们没有明确定义所有权。

你需要清楚地定义谁拥有什么。没有其他办法可以解决这个问题。任意交换shared_ptrweak_ptr的某些用法不会让事情变得更好。

答案 1 :(得分:4)

将您的设计从shared_ptr更改为weak_ptr没有任何好处。获得所有权不是关于使用weak_ptrs,而是关于管理谁在任何相当长的时间内存储shared_ptr。如果我将shared_ptr传递给方法,假设我没有将shared_ptr存储到我的对象中的字段作为该方法的一部分,我没有更改谁拥有该数据。

根据我的经验,使用weak_ptr的唯一原因是当你必须有一个指针循环时,你需要打破这个循环。但首先你应该考虑是否可以修改你的设计以消除循环。

我通常不鼓励混合shared_ptr和raw指针。它不可避免地发生(尽管它可能不应该)原始指针需要传递给一个采用该类型的shared_ptr的函数。 weak_ptr可以安全地转换为shared_ptr,原始指针你运气不好。更糟糕的是,没有经验的shared_ptr的开发人员可能会从该原始指针创建一个新的shared_ptr并将其传递给该函数,从而导致该函数返回时删除该指针。 (我实际上必须在生产代码中解决这个问题,所以是的,确实发生了:))

答案 2 :(得分:3)

听起来你有一个设计问题。 shared_ptr提供 针对特定设计解决方案的简单易用的实现, 但它(或其他任何东西)都可以取代设计。直到你 确定了每种类型物体的实际寿命 应该是,你不应该使用shared_ptr。一旦你完成了 那个,大多数shared_ptr / weak_ptr问题都应该消失。

如果,已经做到了,并确定了一些人的一生 对象确实依赖于其他对象的对象,并且有 在这种依赖关系中,你必须确定(在设计中) 水平,再次)如何管理这些周期---这很有可能, 例如,在这些情况下,shared_ptr不正确 解决方案,或涉及的许多指针只是为了 导航,应该是原始指针。

无论如何,您的问题的答案都在于设计 水平。如果你必须在编码时问它,那么现在是时候了 回到设计。

答案 3 :(得分:2)

有些人是对的:首先,您应该清楚地了解项目中对象的所有权。

shared_ptrs shared ,即“社区拥有”。这可能是也可能不是可取的。所以我建议定义所有权模型,然后不要滥用shared_ptr语义,并且每当所有权不应该“共享”更多时使用普通指针。

使用weak_ptrs会进一步掩盖问题,而不是修复它。