“循環(huán)引用”簡單來說就是:兩個對象互相使用一個 shared_ptr 成員變量指向?qū)Ψ礁爿骸_@樣會引發(fā)一個問題嚷往,其中任何一個對象的引用計數(shù)都為2形病。析構(gòu)時兩個資源引?計數(shù)會減?,于是兩者引?計數(shù)還是大于0坊罢,導(dǎo)致跳出函數(shù)時資源沒有被釋放(離開作用域時兩個對象的析構(gòu)函數(shù)沒有被調(diào)?)
看下面的例子:
#include <memory>
using namespace std;
class father;
class son;
class father
{
public:
shared_ptr<son> son;
public:
~father() //析構(gòu)函數(shù)
{
cout << "father distructor" << endl; //刪除對象
}
};
class son
{
public:
shared_ptr<father> father;
public:
~son()
{
cout << "son distructor" << endl; //刪除對象
}
};
void test(father **f, son **s)
{
shared_ptr<father> pfath(new father());
shared_ptr<son> pson(new son());
*f = pfath.get();
*s = pson.get();
pfath->son = pson;
pson->father = pfath;
cout << "pfath use_count:" << pfath.use_count() << endl; // father對象usecount:2
cout << "pson use_count:" << pson.use_count() << endl; // sond對象usecount:2
}
int main()
{
father *pfather;
son *pson;
test(&pfather, &pson); // test()結(jié)束以后析構(gòu)函數(shù)并沒有被調(diào)用
cout << "pfath use_count:" << pson->father.use_count() << endl; // father對象usecount:1
cout << "pson use_count:" << pfather->son.use_count() << endl; // sond對象usecount:2
return 0;
}
輸出
pfath use_count:2
pson use_count:2
pfath use_count:1
pson use_count:1
可以看到test()結(jié)束以后析構(gòu)函數(shù)并沒有被調(diào)用,會導(dǎo)致資源泄露擅耽。這顯然違背了智能指針的初衷活孩。
解決辦法
使用weak_ptr 來打破循環(huán)引用,它與一個 shared_ptr 綁定乖仇,但卻不參與引用計數(shù)的計算憾儒,不論是否有 weak_ptr 指向询兴,一旦最后一個指向?qū)ο蟮?shared_ptr 被銷毀,對象就會被釋放起趾。
修改上述代碼:
class father
{
public:
weak_ptr<son> son; // shared_ptr >> weak_ptr
public:
~father() //析構(gòu)函數(shù)
{
cout << "son distructor" << endl; //刪除對象
}
};
class son
{
public:
weak_ptr<father> father; // shared_ptr >> weak_ptr
public:
~son()
{
cout << "father distructor" << endl; //刪除對象
}
};
運行輸出:
pfath use_count:1
pson use_count:1
father distructor
son distructor
pfath use_count:0
pson use_count:0