关于此主题已经有几个问题,但我仍然不确定该怎么做:我们的代码库在很多地方使用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,直到我遇到问题(并实现它们),然后修复它们?
感谢您的想法!
另见
答案 0 :(得分:6)
我们没有明确定义所有权。
你需要清楚地定义谁拥有什么。没有其他办法可以解决这个问题。任意交换shared_ptr
与weak_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会进一步掩盖问题,而不是修复它。