在geeksforgeeks上看到一篇介绍shared_ptr的文章,里面提到了Cyclic Dependency。

维基百科中也有详细的介绍Circular dependency
维基百科中提到一种循环依赖关系错误的例子:
a.h

#ifndef A_H
#define A_H

class B;    //forward declaration

class A {
public:
    B* b;
};
#endif //A_H

b.h

#ifndef B_H
#define B_H
 
class A;    //forward declaration

class B {
public:
    A* a;
};
#endif //B_H

main.cpp

#include "a.h"
#include "b.h"
 
int main() {
    A a;
    B b;
    a.b = &b;
    b.a = &a;
}
Circular dependencies may also cause memory leaks by preventing certain very primitive automatic garbage collectors (those that use reference counting) from deallocating unused objects.

我们来看一个shared_ptr循环关系依赖导致引用计数永远不为0,导致内存泄露的例子:

// C++ program to demonstrate shared_ptr
#include <iostream>
#include <memory>
using namespace std;

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()

另外一个例子比较经典,类中实现了双链表,用于遍历对象
a.h

class A {
public:
    static A *first, *last;
    A *previous, *next;

    A();
    ~A();
};

a.cpp

#include "a.h"

A *A::first=0, *A::last=0; // don't put the word static here, that will cause an error

A::A() {
    if (first == 0) first=this; // first A created
    previous = last;
    if (previous != 0) previous->next = this;
    last = this;
    next = 0;
}

A::~A() {
    if (previous != 0) previous->next = next;
    if (next != 0) next->previous = previous;
}

main.cpp

#include <iostream>
#include "a.cpp"

using namespace std;

int main()
{
    A a1;
    cout << "Address of a1 " << &a1<<endl;
    cout << "first " << A::first << " last " << A::last << endl;

    A a2;
    cout << "Address of a2 " << &a2<<endl;
    cout << "first " << A::first << " last " << A::last << endl;

    A a3;
    cout << "Address of a3 " << &a3 << endl;
    cout << "first " << A::first << " last " << A::last << endl;

    A *ptr = A::first;
    while(ptr)
    {
        cout << ptr << endl;
        ptr = ptr->next;
    }
    
    cout << endl;

    ptr = A::last;
    while(ptr)
    {
        cout << ptr << endl;
        ptr = ptr->previous;
    } 
    

    return 0;
}

运行结果:

[root shared_ptr]#./a.out
Address of a1 0x7ffc6c215dd0
first 0x7ffc6c215dd0 last 0x7ffc6c215dd0
Address of a2 0x7ffc6c215de0
first 0x7ffc6c215dd0 last 0x7ffc6c215de0
Address of a3 0x7ffc6c215df0
first 0x7ffc6c215dd0 last 0x7ffc6c215df0
0x7ffc6c215dd0
0x7ffc6c215de0
0x7ffc6c215df0

0x7ffc6c215df0
0x7ffc6c215de0
0x7ffc6c215dd0

一篇完整的介绍

C++单例模式

C++ Singleton design pattern