循環引用-智能指針的死穴之一
來源:程序員人生 發布時間:2015-04-20 08:09:23 閱讀次數:3275次
智能指針的實現思路也體現了C++基于對象的原則,對象應當為自己管理的資源負責,包括資源的分配與釋放,而且最好將資源的釋放與分配弄的自動化1點,典型的實現方法就是在構造函數里分配資源,在析構函數里釋放資源,這樣當其他程序員在使用這個對象時,該對象的資源問題幾近不用額外的操心,即優雅又方便
然后如此完善的東西,也有其不容忽視的地方,直接上代碼:
// share_ptr.cpp : 定義控制臺利用程序的入口點。
//
#include "stdafx.h"
#include "common_class.h"
class B;
class A{
private:
typedef tr1::shared_ptr<B> Item_Type;
public:
explicit A(){};
virtual ~A(){};
public:
void SetB(const Item_Type ptr_B){m_B = ptr_B;}
private:
Item_Type m_B;
};
class B{
private:
typedef tr1::shared_ptr<A> Item_Type;
public:
explicit B(){};
virtual ~B(){};
public:
void SetA(const Item_Type ptr_A){m_A = ptr_A;}
private:
Item_Type m_A;
};
int _tmain(int argc, _TCHAR* argv[])
{
size_t count = 100000;
getchar();//查看內存狀態
while(count--)
{
//new出來的A的援用計數此時為1
shared_ptr<A> a(new A);
//new出來的A的援用計數此時為1
shared_ptr<B> b(new B);
//B的援用計數增加為2
a->SetB(b);
//A的援用計數增加為2
b->SetA(a);
}
getchar();//查看內存狀態
//b先出作用域,B的援用計數減少為1,不為0,所以堆上的B空間沒有被釋放,
//且B持有的A也沒有機會被析構,A的援用計數也完全沒減少
//a后出作用域,同理A的援用計數減少為1,不為0,所以堆上A的空間也沒有被釋放
return 0;
}
兩次查看內存資源狀態結果


結果可知:內存增加了幾近20M,更何況我定義的兩個對象本身不怎樣占資源,如果內部保護了幾個list,結果可想而知!
A和B都相互指著對方吼,“放開我的援用!“,“你先發我的我就放你的!”,因而悲劇產生了。
所以在使用基于援用計數的智能指針時,要特別謹慎循環援用帶來的內存泄漏,循環援用不只是兩方的情況,只要援用鏈成環都會出現問題。固然循環援用本身就說明設計上可能存在1些問題,如果特殊緣由不能不使用循環援用,那可讓援用鏈上的1方持用普通指針(或弱智能指針weak_ptr)便可.
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈