1. 强智能指针shared_ptr循环引用所带来的问题:
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()
{
shared_ptr<A> pa(new A());
shared_ptr<B> pb(new B());
pa->_ptrb = pb;
pb->_ptra = pa;
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
return 0;
}
显而易见,类A中有一个指向类B的shared_ ptr强类型智能指针,类B中有一个指向类A的shared_ ptr强类型智能指针
此时,有两个强智能指针指向了对象A,对象A的引用计数为2。也有两个强智能指针指向了对象B,对象B的引用计数为2。
当主函数return返回后,对象A的引用计数减一变为1,对象B的引用计数减一变为1,此时因为引用计数不为0,所以不能析构对象释放内存,程序结束造成内存泄漏
原理示意图
2. 解决循环交叉引用的问题
怎么解决交叉引用的问题呢?对了,就是引入弱智能指针,还记得吗?我们在使用强弱智能指针的时候,有一个规定,就是创建对象的时候,应该使用它的强智能指针,当其他地方想使用这个对象的时候,应该使用该对象的弱智能指针
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;
cout << ptra.use_count() << endl;
cout << ptrb.use_count() << endl;
return 0;
}
运行结果如下
当主函数return返回后,对象A的引用计数减一变为0,所以正常析构对象A;对象B的引用计数减一变为0,所以正常析构对象B,此时不会造成内存泄漏
因为弱智能指针相当于观察者,是不会引起对象的引用计数增加的,当通过弱智能指针访问对象时,需要先进行lock提升操作,提升成功,证明对象还存在,再通过强智能指针访问对象
3. 总结
shared_ptr: 强智能指针(引起资源引用计数的改变)
weak_ptr: 弱智能指针 (不会引起资源引用计数的改变)
创建对象的时候用shared_ptr强智能指针,别的地方一律用
weak_ptr弱智能指针。