繁体   English   中英

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

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

Effective Modern C++第 137 页的最后一个例子描绘了一个数据结构的场景,其中包含对象ABC ,通过std::shared_ptr以下列方式相互连接:

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

对我来说,这意味着该对象的AC是实例(两个不相关的类,在一般情况)必须包含std::shared_ptr<classOfB>构件。

然后假设我们需要一个从B返回到A的指针,并列出了可用的选项:指针可以是原始的、共享的或弱的,最后一个被选为最佳候选者。

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

我确实理解前两个选项的弱点(啊哈),但我也看到第三个选项要求成员A已经由某个std::shared_ptr管理,否则std::weak_ptr怎么能指向它呢?

然而,这本书并没有提到这个“限制”/假设/任何东西,所以事实是

  • 我错了
  • 我是对的,但由于某种原因,这个假设很明显,我不明白
  • 由于std::weak_ptr需要一个已经存在的std::shared_ptr到同一个对象的确切原因,假设是显而易见的,但我认为这有点奇怪,它甚至在示例的开头都没有提到。

我问这个问题是为了理解这一点。

你是对的,你的第三个要点是正确的。 std::weak_ptr始终引用现有的std::shared_ptr 因此,一旦我们决定 A 将包含一个shared_ptr<BClass>并且 A 的实例作为shared_ptr<AClass>进行管理,我们就可以在后面使用weak_ptr<AClass> - 从 B 到 A 的参考。

在典型的用例中,您可以拥有一个管理三个成员的 D 类shared_ptr<AClass> a; , shared_ptr<BClass> b; shared_ptr<CClass> c; , 然后 D 类中的某个成员函数做了a->SetB(b); , c->SetB(b); , b->SetA(a); , SetB 成员函数使用 shared_ptr's 和 SetA 使用weak_ptr(或在成员函数中转换为weak_ptr)。 正如您所说,如果 D 确实以任何其他方式存储了对 A 的引用,例如原始指针AClass* a; 或一个实例AClass a; ,那么使用weak_ptr 是不可能的。

std::shared_ptr设计的不幸后果是在共享指针管理的依赖图中不会出现循环。 这意味着一旦 A 通过共享指针指向 B,B 就不能以相同的方式指向 A,因为这将导致内存泄漏(两个对象都将保持活动状态)。

std::weak_ptr的主要目的是作为弱引用,但在大多数情况下,它仅用作解决此问题的方法。 但是,如果您首先不通过共享指针管理 A 的生命周期,则 B 无论如何都无法跟踪它,因此使用原始指针、引用(或其他一些外来指针)是唯一的选择。 相反,如果您通过共享指针拥有 A,则weak_ptr是唯一的选择。

在这两种情况下,选择完全取决于您之前管理 A 的决定,这是您在这里必须做的事情(可能通过一个同时引用 A 和 C 的对象)。

暂无
暂无

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

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