C++经典面试题 | 带引用计数的智能指针循环交叉引用问题

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弱智能指针。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值