关于shared_ptr的内存泄漏

关于shared_ptr的内存泄漏

结论:

  1. 当对象存在循环引用时,shared_ptr存在内存泄漏;
  2. 标准库提供了weak_ptr来解决,通过weak_ptr去引用对象,不会增加对象的引用计数;
#include 
#include 
using namespace std;

class B;
class A
{
public:
    A() { cout << "A's constructor ..." << endl; }
    ~A() { cout << "A's destructor ..." << endl; }
    
    std::shared_ptr b;//class A中含有指向class B的shared指针
};

class B
{
public:
    B() { cout << "B's constructor ..." << endl; }
    ~B() { cout << "B's destructor ..." << endl; }

    std::shared_ptr a; //class B 中含有指向class A的shared指针
};

int main() 
{
    std::shared_ptr aa = make_shared(); //aa->object A  aa计数器 1
    //分配了一块内存大小是sizeof(A), 假设该内存的地址是ptr_A
    //该内存由一个共享指针shared_ptr aa来管理,怎么管理呢?
    //维护了ptr_A这块内存的引用计数;截止到目前ptr_A就aa一个对象持有;所以ptr_A的ref_count是1
    cout << "aa's ref_count=" << aa.use_count() << endl;
    std::shared_ptr bb = make_shared(); //bb->object B  bb计数器 1
    //分析同上,ptr_B的ref_count是1
    cout << "bb's ref_count=" << bb.use_count() << endl;

    aa->b = bb;// bb 计数器来到了 2
    //上述操作之后,ptr_B这块内存通过aa->b也可以访问到了,也就是ptr_B的引用计数变到了2
    cout << "after aa->b = bb, aa's ref_count=" << aa.use_count() << "," << "aa.b's ref_count=" << aa->b.use_count() << ",";
    cout << "bb's ref_count=" << bb.use_count() << endl;

/*
    bb->a = aa;// aa 计数器来到了 2
    //上述操作之后,ptr_A这块内存通过bb->a也可以访问到了,也就是ptr_A的引用计数变到了2
    cout << "after bb->a = aa, aa's ref_count=" << aa.use_count() << "," << "bb.a's ref_count=" << bb->a.use_count() << ",";
    cout << "bb's ref_count=" << bb.use_count() << endl;

    //析构函数开始执行
    //首先要释放的是bb, ptr_B的引用计数减1到了1;所以ptr_B指向的B对象还不能释放
    //然后要释放的是aa, ptr_A的引用计数减1到了1;所以ptr_A指向的A对象还不能释放
    
    //然后就内存泄漏了
    具体输出如下:
    A's constructor ...
    aa's ref_count=1
    B's constructor ...
    bb's ref_count=1
    after aa->b = bb, aa's ref_count=1,aa.b's ref_count=2,bb's ref_count=2
    after bb->a = aa, aa's ref_count=2,bb.a's ref_count=2,bb's ref_count=2
*/

/*
    //bb->a = aa;// aa 计数器来到了 2
    //假设如果没有bb->a=aa这个操作,也就说没有循环引用;
    //析构函数开始执行
    //首先要释放的是bb, ptr_B的引用计数减1到了1;所以ptr_B指向的B对象还不能释放
    //然后要释放的是aa, ptr_A的引用计数减1到了0;所以ptr_A指向的A对象可以释放了
    //前面aa对象释放时,内部的b也同时被销毁,ptr_B的ref_count减到了0,ptr_B也可以释放了
    具体输出如下:
    A's constructor ...
    aa's ref_count=1
    B's constructor ...
    bb's ref_count=1
    after aa->b = bb, aa's ref_count=1,aa.b's ref_count=2,bb's ref_count=2
    A's destructor ...
    B's destructor ...
*/
    return 0;
}

你可能感兴趣的:(关于shared_ptr的内存泄漏)