一、问题描述

在使用shared_ptr时,如果出现了循环引用(如链表节点的next指向),就会导致内存泄漏。

例如以下两个类,内部互相有一个指向对方的智能指针,在生存空间结束后就不会被释放掉:

#include <iostream>
#include <memory>
using namespace std;

class CTestB;

class CTestA {
public:
    shared_ptr<CTestB> b;
    CTestA() {
        cout << "CTestA()" << endl;
    }
    ~CTestA() {
        cout << "~CTestA()" << endl;
    }
};

class CTestB {
public:
    shared_ptr<CTestA> a;
    CTestB() {
        cout << "CTestB()" << endl;
    }
    ~CTestB() {
        cout << "~CTestB()" << endl;
    }
};

int main() {
    shared_ptr<CTestA> a(new CTestA);
    shared_ptr<CTestB> b(new CTestB);

    cout << "a.use_count = " << a.use_count() << endl;
    cout << "b.use_count = " << b.use_count() << endl;

    a->b = b;
    b->a = a;

    cout << "a.use_count = " << a.use_count() << endl;
    cout << "b.use_count = " << b.use_count() << endl;

    return 0;
}

编译后的运行程序的结果:

原因很简单,a->b = b导致b的引用计数增加,b->a = a导致a的引用计数增加,在程序运行完后,a、b自行析构引用计数都会减一,但是此时引用计数都是1,因此不会释放。

二、解决方法

shared_ptr循环引用要通过weak_ptr来解决,weak_ptr也是智能指针的一种,不过它是一种弱引用,不会增加智能指针的引用计数。

分别修改两个类为以下形式:

class CTestA {
public:
    weak_ptr<CTestB> b;
    // ...
}

class CTestB {
public:
    weak_ptr<CTestA> a;
    // ...
}

运行结果:

最后修改:2019 年 04 月 20 日
如果觉得我的文章对你有用,请随意赞赏