關(guān)于shared_ptr的內(nèi)存泄漏

關(guān)于shared_ptr的內(nèi)存泄漏

結(jié)論:

  1. 當(dāng)對象存在循環(huán)引用時,shared_ptr存在內(nèi)存泄漏;
  2. 標(biāo)準(zhǔn)庫提供了weak_ptr來解決,通過weak_ptr去引用對象,不會增加對象的引用計數(shù);
#include <iostream>
#include <memory>
using namespace std;

class B;
class A
{
public:
    A() { cout << "A's constructor ..." << endl; }
    ~A() { cout << "A's destructor ..." << endl; }
    
    std::shared_ptr<B> 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> a; //class B 中含有指向class A的shared指針
};

int main() 
{
    std::shared_ptr<A> aa = make_shared<A>(); //aa->object A  aa計數(shù)器 1
    //分配了一塊內(nèi)存大小是sizeof(A), 假設(shè)該內(nèi)存的地址是ptr_A
    //該內(nèi)存由一個共享指針shared_ptr aa來管理,怎么管理呢?
    //維護了ptr_A這塊內(nèi)存的引用計數(shù);截止到目前ptr_A就aa一個對象持有;所以ptr_A的ref_count是1
    cout << "aa's ref_count=" << aa.use_count() << endl;
    std::shared_ptr<B> bb = make_shared<B>(); //bb->object B  bb計數(shù)器 1
    //分析同上,ptr_B的ref_count是1
    cout << "bb's ref_count=" << bb.use_count() << endl;

    aa->b = bb;// bb 計數(shù)器來到了 2
    //上述操作之后,ptr_B這塊內(nèi)存通過aa->b也可以訪問到了,也就是ptr_B的引用計數(shù)變到了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 計數(shù)器來到了 2
    //上述操作之后,ptr_A這塊內(nèi)存通過bb->a也可以訪問到了,也就是ptr_A的引用計數(shù)變到了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;

    //析構(gòu)函數(shù)開始執(zhí)行
    //首先要釋放的是bb, ptr_B的引用計數(shù)減1到了1;所以ptr_B指向的B對象還不能釋放
    //然后要釋放的是aa, ptr_A的引用計數(shù)減1到了1;所以ptr_A指向的A對象還不能釋放
    
    //然后就內(nèi)存泄漏了
    具體輸出如下:
    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 計數(shù)器來到了 2
    //假設(shè)如果沒有bb->a=aa這個操作,也就說沒有循環(huán)引用;
    //析構(gòu)函數(shù)開始執(zhí)行
    //首先要釋放的是bb, ptr_B的引用計數(shù)減1到了1;所以ptr_B指向的B對象還不能釋放
    //然后要釋放的是aa, ptr_A的引用計數(shù)減1到了0;所以ptr_A指向的A對象可以釋放了
    //前面aa對象釋放時,內(nèi)部的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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容