weak_ptr和父子循环依赖

发布于 2024-10-08 01:42:30 字数 489 浏览 7 评论 0原文

我目前有类似以下内容:

class Parent
{
    //just a single child... for sake of simplicity
    //no other class holds a shared_ptr reference to child
    shared_ptr<Child> _child; 
    System * getSystem() {...}
}

class Child
{
    weak_ptr<Parent> _parent;
    ~Child 
    { 
        _parent.lock()->getSystem()->blah(); 
    }
}

Child 析构函数总是崩溃,因为当 ~Child() 运行时 _parent 总是过期。对于这种奇怪的现象有典型的解决方案吗?

简而言之,有没有办法在 ~Child 完成之前不销毁 _parent ?

I currently have something similar to the following:

class Parent
{
    //just a single child... for sake of simplicity
    //no other class holds a shared_ptr reference to child
    shared_ptr<Child> _child; 
    System * getSystem() {...}
}

class Child
{
    weak_ptr<Parent> _parent;
    ~Child 
    { 
        _parent.lock()->getSystem()->blah(); 
    }
}

The Child destructor always crashes, since when ~Child() runs _parent is always expired. Is there a typical solution to this weirdness?

In short, is there a way to not destroy _parent until ~Child finishes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

挽袖吟 2024-10-15 01:42:30

因为当子对象的析构函数被调用时,父对象的析构函数已经运行(成员对象的 dtor 在包含对象的 dtor 之后运行),即使子对象持有指向父对象的普通指针,调用调用 ~Child() 时,父级的成员函数将无效。

您可以通过让 Child 在早些时候调用 getSystem() 并缓存结果来解决此问题。也许在 Child 的构造函数中(如果它当时有对父级的引用),或者可能可以添加一个接口,以便 Parent 可以让子级知道它需要从当时的父级收集销毁过程中可能需要的任何东西。

我知道这两个都不是一个很好的解决方案(它增加了对象的耦合) - 希望有人会发布更好的选择。

Since by the time the destructor for the the child gets called, the parent's destructor has already run (dtors for member objects get run after the dtor for the containing object), even if the child was holding a plain pointer to the parent, calling the parent's member function would be invalid by the time ~Child() was called.

You might be able to work around this by having Child call getSystem() at some earlier point and cache the result. Maybe in the constructor of Child (if it has a reference to the parent at the time) or maybe there can be an interface added so that Parent can let the child know it needs to collect whatever it might need during destruction from the parent at that time.

I understand that neither of these is a great solution (it increases coupling of the objects) -hopefully someone will post a better option.

给妤﹃绝世温柔 2024-10-15 01:42:30

最好删除循环引用,但如果不能,您可以强制在 Parent 完全消失之前销毁 Child。在析构函数中,显式调用 Child 上的 Reset()。假设没有其他共享指针,这将迫使它立即被销毁。

警告,如果 Parent 实际上是基类,那么它的所有子类都将被销毁。虚函数调用可能不会按预期运行。

Removing the circular reference is preferable, but if you cannot you can force Child to be destroyed before Parent is completely gone. In the destructor, explicitly call reset() on Child. This will force it to be destroyed immediately, assuming there are no other shared_ptrs to it.

Warning, if Parent is actually a base class all of it's subclasses will alreayd have been destroyed. Virtual function calls will probably not behave as expected.

以酷 2024-10-15 01:42:30

weak_ptr 的第一条规则:始终检查锁定(返回指针或异常):毕竟使用weak_ptr 的真正原因是它不控制所指向对象的生命周期。

First rule of weak_ptr: always check the locking (returned pointer or exception): after all the real reason to use weak_ptr is that it doesn't control the life-cycle of the pointed object.

一身仙ぐ女味 2024-10-15 01:42:30

_parent.lock()->

这里你假设 lock 会成功,并且你的 weak_ptr 当时还没有过期。

因此,您根本不应该使用weak_ptr,而应该使用shared_ptr

如果您不滥用<代码>weak_ptr。您将看到有两个对象试图管理彼此的生命周期,并且您的设计需要修复。 (将 weak_ptr 添加到混合中并不能修复设计。)

_parent.lock()->

Here you assume that lock will succeed, IOW that your weak_ptr will not have expired at that time.

So, you should not be using a weak_ptr at all, but a shared_ptr instead.

Things will be much more clear if you do not misuse weak_ptr. You will see that you have two objects that try to manage each other lifetime, and that your design needs to be fixed. (Throwing weak_ptr into the mix does not fix a design.)

擦肩而过的背影 2024-10-15 01:42:30

仅从您发布的代码来看,这应该可行。唯一删除_child的是父类。

因此有两种可能性:首先,其他东西也有对 _child 指针的引用,并使其引用计数保持活动状态,然后parent 被销毁。然后最终任何其他抓住孩子的东西也会被摧毁,然后杀死孩子。

场景 2 是对 getSystem 的调用取决于您未向我们展示的其他一些成员,并且这些成员在 _child shared_ptr 之前被删除。

Just from the code you posted this should work. The only thing deleting _child is the parent class.

So there are two possibilites: First, something else also has a reference to the _child pointer, and keeps it ref count alive, and then parent is destroyed. Then eventually whatever else is holding onto child is also destroyed, killing off the child then.

Scenario 2 is that the call to getSystem depends on some other members youre not showing us, and those are getting deleted before the _child shared_ptr is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文