C++ shared_ptr循环引用疑问:Com持有Sup实例为何未触发循环引用
循环引用的前提条件
shared_ptr 产生循环引用必须满足核心前提:
- 至少两个对象互相持有对方的 shared_ptr 所有权
- 双方的引用计数都因为对方的持有,无法降低到0,导致所有关联对象都无法触发析构回收
代码运行全流程拆解
我们逐行跟踪执行过程和引用计数变化即可清晰理解:
- 执行
auto sup = std::make_shared<Sup>(1);- 生成 id 为1的 Sup 对象,Sup 引用计数为1(仅栈变量
sup持有) - 输出
***CS: 1
- 生成 id 为1的 Sup 对象,Sup 引用计数为1(仅栈变量
- 执行
auto com = std::make_shared<Com>(1, sup);- 生成 id 为1的 Com 对象,Com 内部成员
supPtr_拷贝sup,Sup 引用计数升至2 - Com 引用计数为1(仅栈变量
com持有) - 输出
***ConstrCom: 1
- 生成 id 为1的 Com 对象,Com 内部成员
- 执行创建
com2、com3的逻辑- 每创建一个 Com 对象,Sup 的引用计数各加1,完成创建后 Sup 引用计数为4(栈变量
sup+ 3个Com的supPtr_) - 三个 Com 对象的引用计数各为1
- 每创建一个 Com 对象,Sup 的引用计数各加1,完成创建后 Sup 引用计数为4(栈变量
- 执行
sup->d();- 进入方法后执行
auto com = std::make_shared<Com>(7, shared_from_this());:调用shared_from_this()拿到当前 Sup 对象的 shared_ptr,Sup 引用计数升至5;生成id为7的Com对象,输出***ConstrCom: 7,该 Com 的引用计数为1(仅d方法内的局部变量com持有) - d方法执行结束,局部变量
com出作用域销毁:id为7的Com引用计数降到0,触发析构输出###DestrCom: 7;Com内部的supPtr_同步销毁,Sup 引用计数降回4
- 进入方法后执行
- main函数执行到return 0,栈变量按创建逆序销毁:
- 销毁
com3:Com引用计数降到0,析构输出###DestrCom: 3,Sup引用计数降到3 - 销毁
com2:Com引用计数降到0,析构输出###DestrCom: 2,Sup引用计数降到2 - 销毁
com:Com引用计数降到0,析构输出###DestrCom: 1,Sup引用计数降到1 - 销毁
sup:Sup引用计数降到0,析构输出###DestrSup 1
- 销毁
无循环引用的核心原因
这段代码里根本不存在双向持有所有权的情况:Sup 类本身没有任何 shared_ptr<Com> 类型的成员变量,不会长期持有任何 Com 对象的所有权;d方法内创建的Com对象是局部变量,出作用域就直接销毁,不会被Sup保留。
如果修改代码,给Sup类增加shared_ptr<Com> com_成员,并且在d方法中将创建的Com对象赋值给com_,才会形成“Sup持有Com、Com持有Sup”的双向持有关系,触发循环引用。
内容的提问来源于stack exchange,提问作者Dean Marek
相关产品推荐
相关产品推荐

