[英]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 页的最后一个例子描绘了一个数据结构的场景,其中包含对象
A
、 B
和C
,通过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.对我来说,这意味着该对象的类
A
和C
是实例(两个不相关的类,在一般情况)必须包含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然而,这本书并没有提到这个“限制”/假设/任何东西,所以事实是
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.