2011-03-23 76 views
7

已经有几个关于这个主题的问题,但我仍然不确定该怎么做:我们的代码库在很多地方使用shared_ptr。我不得不承认,我们在写作时没有明确界定所有权。传递给方法时,我应该将shared_ptr转换为weak_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

Would shared_ptr &ptr be better? – DanDan 2011-03-23 16:01:00

+1

“检测它们并不容易” - 然后确实需要在设计过程中添加更多步骤。班级关系图上的明暗线条,或任何需要的东西。你也可以考虑用原始指针而不是弱指针来破坏循环,对于大多数不对称关系来说,“所有者”永远不会在所有“非所有者”之前被破坏。 – 2011-03-23 16:01:44

+1

@DanDan:我不这么认为,请参阅http://stackoverflow.com/questions/327573/c-passing-references-to-boostshared-ptr – Philipp 2011-03-23 16:03:29

回答

6

见我们没有界定清楚的所有权。

您需要清楚地说明谁拥有什么。没有其他办法可以解决这个问题。随意更换shared_ptrweak_ptr的一些用途不会让事情变得更好。

+0

好吧,我想这应该不会太难,因为设计(但还没有:-))太糟糕了。然而,问题依然存在:我应该只在检测到圈子(如果还有其他地方)或所有对象/方法没有所有权的地方引入weak_ptrs吗? – Philipp 2011-03-23 17:47:29

+1

@Phillip - 如果你看看你给出的例子,在传递weak_ptr和shared_ptr之间的行为没有区别。要使用weak_ptr,必须先从它创建一个shared_ptr,这与首先传递shared_ptr的效果相同。 – Nathanael 2011-03-23 18:46:29

2

有些人是对的:你首先应该清楚地了解项目中物体的所有权。

shared_ptrs是共享,即“由社区拥有”。这可能或不可取。因此,我建议定义所有权模型,然后不要滥用shared_ptr语义,并在所有权不应该“共享”更多时使用普通指针。

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

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并将其传递给该函数,从而导致该函数返回时该指针被删除。 (我实际上必须修复生产代码中的这个错误,所以是的,它确实发生:))

+0

“_It不可避免地发生_(...)”这个解释是我在SO(或其他地方)看到的weak_ptr的极少数阐述性理由之一。谢谢。 – curiousguy 2012-07-22 14:35:50

3

听起来像你有设计问题。 shared_ptr为特定设计解决方案提供了 一个简单易用的实现,但它(而不是其他任何)可以替代该设计。直到您 已确定每种类型对象 的实际生命周期应该是什么时,您都不应该使用shared_ptr。完成 之后,大部分shared_ptr/weak_ptr问题应该消失。

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

无论如何,您的问题的答案驻留在设计 的水平。如果你在编码时不得不问,那么现在是时候去设计 。

相关问题