C++中std::shared_ptr与std::weak_ptr的析构调用顺序异常问题
问题分析:为何B的析构函数先于A执行?
你的核心误解在于混淆了栈上shared_ptr对象的析构顺序和它们托管的堆对象的析构顺序,两者并不完全一致,关键在于std::shared_ptr的引用计数机制。
引用计数变化全过程
我们一步步梳理代码中引用计数的变化:
- 创建栈上
shared_ptr<B> b:B对象的引用计数变为1(weak_ptr不参与计数,所以a->b_weak_ptr = b不会改变B的计数)。 - 创建栈上
shared_ptr<A> a:A对象的引用计数变为1。 - 执行
b->a_ptr = a:A对象的引用计数增加到2(栈上的a和B成员的a_ptr都指向A)。
作用域结束时的析构流程
当局部作用域结束,栈上的a和b会按声明的逆序销毁(先销毁a,再销毁b),但这只是栈上的智能指针对象销毁,堆上的A、B对象是否销毁取决于引用计数是否归零:
- 销毁栈上的
a:A的引用计数从2减到1,计数未归零,A对象不销毁。 - 销毁栈上的
b:B的引用计数从1减到0,触发B对象的析构。 - B对象析构时,会销毁其成员
a_ptr(shared_ptr<A>):此时A的引用计数从1减到0,触发A对象的析构。
这就导致输出中B destructor called先出现,随后才是A destructor called。
补充验证
如果想让A先析构,可以调整引用关系,比如让B持有A的weak_ptr,A持有B的shared_ptr;或者在作用域结束前手动断开b->a_ptr的引用(执行b->a_ptr.reset()),这样栈上a销毁时A的计数直接归零,A会先析构。
内容的提问来源于stack exchange,提问作者哈哈哇
相关产品推荐
相关产品推荐

