一、shared_ptr 的循环引用示例及其详解
产生原因详解:
根据代码执行顺序,share_ptr指针指向new创建的一个Person对象,也就是图中栈空间的person指针指向了堆空间的Person对象,引用计数为1,同理,car指针也指向了堆空间的Car对象,引用计数亦为1。
接下来,Person对象里的成员m_car指向Car对象,Car对象的引用计数加1后为2,Car对象的m_person也指向Person对象,Person对象引用计数也加1为2。
若此时代码执行结束,栈空间上的car指针先进行释放,Car对象的引用计数减1后为1,后释放person指针,Person对象的引用计数也减为1。由于Person对象和Car对象都是建立再堆空间上,两者相互依赖,都在等待对方释放。
可以看到,这个例子中,堆空间里的 Person对象 与 Car对象互相使用着,导致双方的 shared_ptr 强引用数量不会为0,所以不会自动释放内存,产生了内存泄漏。
二、循环引用的解决方案
循环引用的解决方案是使用 weak_ptr。
weak_ptr:
- weak_ptr 会对一个对象产生弱引用
- weak_ptr 可以指向对象解决 shared_ptr 的循环引用问题
weak_ptr作用详解:
根据之前的分析可知,前三句代码执行完后,Person对象的引用计数为1,Car对象的引用计数为2。而第四条语句car->m_person = person执行的便是途中虚线弱引用的语句,不增加Person对象的引用计数。因此,Person对象的引用计数为1,Car对象的引用计数为2。
若此时代码执行结束,栈空间上的car指针先进行释放,Car对象的引用计数减1为1,后释放person指针,Person对象的引用计数减1后为0,Person对象释放内存空间,因此m_car成员函数也得到释放,Car对象引用计数减1后为0,Car对象也得到释放。因此不会产生内存泄漏。
总结
本文章参考【C++】智能指针(auto_ptr,shared_ptr,unique_ptr)及 shared_ptr 强引用原理中shared_ptr 的循环引用和weak_ptr部分的扩展讲解,以上仅为个人的理解,并辅以直白的话语说明例子中想表达的意思,其中不足之处希望多多指正~