智能指针的交叉引用问题,是如下代码发生的问题,导致的结果是对象无法析构,资源无法释放,问题严重!
class B;
class A
{
public:
A(){cout<<"A()"<<endl;}
~A(){cout<<"~A()"<<endl;}
shared_ptr<B> _ptrb;
};
class B
{
public:
B(){cout<<"B()"<<endl;}
~B(){cout<<"~B()"<<endl;}
shared_ptr<A> _ptra;
};
int main(int argc, char* argv[])
{
shared_ptr<A> ptra(new A());
shared_ptr<B> ptrb(new B());
ptra->_ptrb = ptrb;
ptrb->_ptra = ptra;
return 0;
}
显而易见,类A中有一个指向类B的shared_ptr强类型智能指针,类B中有一个指向类A的shared_ ptr强类型智能指针
此时,有两个强智能指针指向了对象A,对象A的引用计数为2。也有两个强智能指针指向了对象B,对象B的引用计数为2。对象A与对象B的关系如图所示 :
当主函数return返回后,对象A的引用计数减一变为1,对象B的引用计数减一变为1,此时因为引用计数不为0,所以不能析构对象释放内存,程序结束造成内存泄漏。
解决方法:将类A和类B中的shared_ptr强智能指针都换成weak_ptr弱智能指针。我们在使用强弱智能指针的时候,有一个规定,就是创建对象的时候,持有它的强智能指针,当其他地方想使用这个对象的时候,应该持有该对象的弱智能指针。
class B;
class A
{
public:
A(){cout<<"A()"<<endl;}
~A(){cout<<"~A()"<<endl;}
weak_ptr<B> _ptrb; //其他地方持有对象的弱智能指针
};
class B
{
public:
B(){cout<<"B()"<<endl;}
~B(){cout<<"~B()"<<endl;}
weak_ptr<A> _ptra; //其他地方持有对象的弱智能指针
};
int main(int argc, char* argv[])
{
shared_ptr<A> ptra(new A()); //创建对象时持有强智能指针
shared_ptr<B> ptrb(new B()); //创建对象时持有强智能指针
ptra->_ptrb = ptrb;
ptrb->_ptra = ptra;
return 0;
}
weak_ptr弱智能指针,虽然有引用计数,但实际上它并不增加计数,而是只观察对象的引用计数,weak_ptr的引用计数指的是有多少个weak_ptr在观察同一个shared_ptr。而shared_ptr强智能指针的引用计数是对资源的引用计数所以此时对象A的引用计数只为1,对象B的引用计数也只为1。此时对象A与对象B的关系如图所示 :
当主函数return返回后,对象A的引用计数减一变为0,所以正常析构对象A;对象B的引用计数减一变为0,所以正常析构对象B,此时不会造成内存泄漏。
总结:
(1)创建对象的时候用shared_ptr强智能指针,别的地方一律持有weak_ptr弱智能指针,否则析构顺序有可能出现错误。
(2)当通过弱智能指针访问对象时,需要先进行lock提升操作,提升成功,证明对象还存在,再通过强智能指针访问对象。
参考:http://blog.csdn.net/qq_36953135/article/details/76998104