C++ 共享ptr的循环依赖性问题是什么?

C++ 共享ptr的循环依赖性问题是什么?,c++,shared-ptr,weak-ptr,C++,Shared Ptr,Weak Ptr,我阅读了有关共享指针的内容,并了解如何使用。但我从未理解共享指针的循环依赖性问题,以及弱指针将如何解决这些问题。谁能把这个问题解释清楚吗?这个问题没有那么复杂。让-->表示共享指针: The rest of the program --> object A --> object B ^ | \ |

我阅读了有关共享指针的内容,并了解如何使用。但我从未理解共享指针的循环依赖性问题,以及弱指针将如何解决这些问题。谁能把这个问题解释清楚吗?

这个问题没有那么复杂。让
-->
表示共享指针:

The rest of the program  --> object A --> object B
                                    ^     |
                                     \    |
                                      \   v
                                        object C
因此,我们有一个共享指针的循环依赖关系。每个对象的引用计数是多少

A:  2
B:  1
C:  1
现在假设程序的其余部分(或者至少是程序中保存指向的共享指针的部分)被销毁。然后,A的引用计数减少1,因此循环中每个对象的引用计数为1。那么什么被删除了呢?没有什么。但是我们想要删除什么呢?一切,因为程序的其余部分再也无法到达我们的任何对象

因此,本例中的修复方法是将从C到A的链接更改为弱指针。弱指针不会影响其目标的引用计数,这意味着当程序的其余部分释放A时,其引用计数将达到0。所以它被删除了,B也被删除了,C也被删除了

不过,在程序的其余部分发布A之前,C可以通过锁定弱指针随时访问A。这会将其升级为共享指针(并将a的引用计数增加到2),只要C正在积极处理a。这意味着,如果a在进行此操作时被释放,则其引用计数只会下降到1。C中使用A的代码不会崩溃,只要短期共享指针被破坏,A就会被删除。它位于锁定弱指针的代码块的末尾

一般来说,决定将弱指针放在何处可能很复杂。为了选择打破循环的位置,循环中的对象之间需要某种不对称。在这种情况下,我们知道A是程序其余部分引用的对象,因此我们知道,打破循环的地方是指向A的任何地方

shard_ptr<A> <----| shared_ptr<B> <------
    ^             |          ^          |
    |             |          |          |
    |             |          |          |
    |             |          |          |
    |             |          |          |
class A           |     class B         |
    |             |          |          |
    |             ------------          |
    |                                   |
    -------------------------------------
正如我们从输出中看到的,A和B指针从未被删除,因此内存泄漏


为了避免这样的问题,只需在类A中使用弱ptr,而不是更合理的共享ptr。

如果你需要谷歌银行的另一个关键字,它也被称为
retain cycle
。我现在明白了。感谢您的清晰解释。不确定这是否是解释循环依赖关系的正确示例。引用计数保存在控制块内,所有共享PTR A、B、C将指向同一控制块,计数=3。我认为这还不够解释。如果类
B
的对象被破坏,会发生什么?在“为虚拟”的解释中,它破坏了自身内部的对象。因此,它调用对
共享的\u ptr
对象的销毁,从而导致类
A
对象的销毁。好的,
A
销毁指向
B的
对象的
共享\u ptr
B
的哪个状态将看到
A
:已销毁/半销毁/仍然存在?然后呢?为什么跑步时会忽略这种行为?为什么它不抛出异常?
class B;

class A
{
    shared_ptr<B> sP1; // use weak_ptr instead to avoid CD

public:
    A() {  cout << "A()" << endl; }
    ~A() { cout << "~A()" << endl; }

    void setShared(shared_ptr<B>& p)
    {
        sP1 = p;
    }
};

class B
{
    shared_ptr<A> sP1;

public:
    B() {  cout << "B()" << endl; }
    ~B() { cout << "~B()" << endl; }

    void setShared(shared_ptr<A>& p)
    {
        sP1 = p;
    }
};

int main()
{
    shared_ptr<A> aPtr(new A);
    shared_ptr<B> bPtr(new B);

    aPtr->setShared(bPtr);
    bPtr->setShared(aPtr);

    return 0;  
}
A()
B()