C++ shared_ptr智能指针循环引用造成的内存泄露

C++ shared_ptr智能指针循环引用造成的内存泄露

概述

初开始看别人解释循环引用的时候,觉得理解了,但是当我使用到的时候突然就理解卡壳了,下面就说一下我的拨乱反正的思路历程。

关于shared_ptr循环引用的代码

#include <memory>
#include <iostream>
class TB;
class TA
{
public:
	~TA(){
		std::cout << "de TA" << std::endl;
	}
	std::shared_ptr<TB> tb;
};

class TB
{
public:
	~TB(){
		std::cout << "de TB" << std::endl;
	}
	std::shared_ptr<TA> ta;
};

int main()
{
	{
		auto a = std::make_shared<TA>(); // step1
		auto b = std::make_shared<TB>(); // step2

		a->tb = b; // step3
		b->ta = a; // step4
        // step 5
	} 
    // step6
	return 0;
}

我测试了代码,结果确实没有打印,也就是说这样的代码确实造成了内存泄露。

推导方法

  • Q: 智能指针的实现是基于引用计数的,那么智能指针又是如何实现引用计数的增加和减少呢?

  • A: 其实就是利用了类的析构函数,智能指针也是一个类,在给一个智能指针赋值的过程中就会对指向对象的引用加1;在智能指针超出作用域的时候智能指针对象就会析构,那么就会对指向对象的引用减1,如果减到0,智能指针就会删除指向对象。

  • 所以我们分析引用增减的时候就是分析智能指针对象什么时候析构。

正确理解下的正确推导

  1. 在程序执行到 step1 的时候, 创建智能指针a,并赋值TA的对象,TA的对象引用加1;
  2. 在程序执行到 step2 的时候,创建智能指针b,并赋值TB的对象,TB的对象引用加1;
  3. 在程序执行到 step3 的时候,给a->tb赋值TB的对象,TB的对象引用加1;
  4. 在程序执行到 step4 的时候,给b->ta赋值TA的对象,TA的对象引用加1;
  5. 在程序执行到 step5 的时候,TA的对象应用为2,TB的对象应用为2;
  6. 在程序执行到 step6 的时候,b智能指针超出作用域开始析构,指向的TB对象引用减1;a智能指针超出作用域开始析构,指向的TA对象引用减1;
  7. 此时TA的对象应用为1,TB的对象应用为1;

错误理解

到step6的时候我潜意识里认为是 TB和TA对象开始析构,而不是智能指针的析构,造成了错误理解,所以这里特别提醒读者一定要区分开 指向对象 和 智能指针对象。

避免循环引用

那就是使用不增加引用的weak_ptr

更多

我的一个3D引擎DEMO项目也是使用了智能指针,在使用上有些心得,在此也分享给大家。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值