简体   繁体   English

了解 Scott Meyers 的第三个 std::weak_ptr 示例

[英]Understanding of Scott Meyers' third example of std::weak_ptr

The final example at page 137 of Effective Modern C++ draws the scenario of a data structure with objects A , B , and C in it, connected to each other via std::shared_ptr in the following way: Effective Modern C++第 137 页的最后一个例子描绘了一个数据结构的场景,其中包含对象ABC ,通过std::shared_ptr以下列方式相互连接:

   std::shared_ptr       std::shared_ptr
A ─────────────────▶ B ◀───────────────── C

To me, this implies that the classes which objects A and C are instance of (two unrelated classes, in general) must contain a std::shared_ptr<classOfB> member.对我来说,这意味着该对象的AC是实例(两个不相关的类,在一般情况)必须包含std::shared_ptr<classOfB>构件。

Then the supposition is made that we need a pointer from B back to A , and the available options are listed: the pointer can be raw, shared, or weak, and the last one is picked up as the best candidate.然后假设我们需要一个从B返回到A的指针,并列出了可用的选项:指针可以是原始的、共享的或弱的,最后一个被选为最佳候选者。

   std::shared_ptr       std::shared_ptr
A ─────────────────▶ B ◀───────────────── C
▲                    │
│    std::weak_ptr   │
└────────────────────┘

I do understand the weaknesses (ahahah) of the first two alternatives, but I also see that the third alternative requires that member A be already managed by some std::shared_ptr , otherwise how can a std::weak_ptr point to it at all?我确实理解前两个选项的弱点(啊哈),但我也看到第三个选项要求成员A已经由某个std::shared_ptr管理,否则std::weak_ptr怎么能指向它呢?

However the book does not refer to this "limitation"/assumption/whatever, so the truth is either然而,这本书并没有提到这个“限制”/假设/任何东西,所以事实是

  • I'm wrong我错了
  • I'm right but that assumption is obvious for some reason I don't understand我是对的,但由于某种原因,这个假设很明显,我不明白
  • The assumption is obvious for the exact reason that a std::weak_ptr needs an already existing std::shared_ptr to the same object, but it's a bit strange it's not even mentioned at the beginning of the example, I think.由于std::weak_ptr需要一个已经存在的std::shared_ptr到同一个对象的确切原因,假设是显而易见的,但我认为这有点奇怪,它甚至在示例的开头都没有提到。

and I'm asking this question to understand this.我问这个问题是为了理解这一点。

You're right, and your third bullet point is correct.你是对的,你的第三个要点是正确的。 A std::weak_ptr always refers to an existing std::shared_ptr . std::weak_ptr始终引用现有的std::shared_ptr So, it is once we've made the decision that A is going to contain a shared_ptr<BClass> and that the instances of A are being managed as shared_ptr<AClass> 's that we can use a weak_ptr<AClass> for the back-reference from B to A.因此,一旦我们决定 A 将包含一个shared_ptr<BClass>并且 A 的实例作为shared_ptr<AClass>进行管理,我们就可以在后面使用weak_ptr<AClass> - 从 B 到 A 的参考。

In a typical use case, you could have a D-class that manages three members shared_ptr<AClass> a;在典型的用例中,您可以拥有一个管理三个成员的 D 类shared_ptr<AClass> a; , shared_ptr<BClass> b; , shared_ptr<BClass> b; and shared_ptr<CClass> c;shared_ptr<CClass> c; , and then some member function in D-class does a->SetB(b); , 然后 D 类中的某个成员函数做了a->SetB(b); , c->SetB(b); , c->SetB(b); , b->SetA(a); , b->SetA(a); , with the SetB member functions using shared_ptr's and SetA using a weak_ptr (or converting to weak_ptr within the member function). , SetB 成员函数使用 shared_ptr's 和 SetA 使用weak_ptr(或在成员函数中转换为weak_ptr)。 As you rightly say, if D did store the reference to A in any other way like, say, a raw pointer AClass* a;正如您所说,如果 D 确实以任何其他方式存储了对 A 的引用,例如原始指针AClass* a; or an instance AClass a;或一个实例AClass a; , then using a weak_ptr would simply not be possible. ,那么使用weak_ptr 是不可能的。

The unfortunate consequence of the design of std::shared_ptr is that no cycles can appear in the dependency graph managed by shared pointers. std::shared_ptr设计的不幸后果是在共享指针管理的依赖图中不会出现循环。 This means that once A points to B via a shared pointer, B cannot point the same way to A since that will lead to a memory leak (both objects will keep themselves alive).这意味着一旦 A 通过共享指针指向 B,B 就不能以相同的方式指向 A,因为这将导致内存泄漏(两个对象都将保持活动状态)。

std::weak_ptr serves its primary purpose as a weak reference, but most of the times, it is used only as a fix for this issue. std::weak_ptr的主要目的是作为弱引用,但在大多数情况下,它仅用作解决此问题的方法。 However, if you don't manage the lifetime of A via a shared pointer in the first place, B has no way of tracking it anyway, so using a raw pointer, a reference (or some other exotic pointer) is the only option.但是,如果您首先不通过共享指针管理 A 的生命周期,则 B 无论如何都无法跟踪它,因此使用原始指针、引用(或其他一些外来指针)是唯一的选择。 Conversely, if you own A via a shared pointer, weak_ptr is the only option.相反,如果您通过共享指针拥有 A,则weak_ptr是唯一的选择。

In both cases, the choice completely depends on your prior decision of managing A, which is something you'd had to do here (possibly via an object that refers to both A and C).在这两种情况下,选择完全取决于您之前管理 A 的决定,这是您在这里必须做的事情(可能通过一个同时引用 A 和 C 的对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM