C++中覆盖shared_ptr指向对象时旧内存未提前释放的原因
我编写了一段用于实验的C++代码:
#include<iostream> #include<memory> class TestClass { public: TestClass(int a, int b) : mA(a), mB(b) { std::cout << "constructor" << std::endl; } ~TestClass() { std::cout << "destructor" << std::endl; } private: int mA; int mB; }; int main(){ auto classPtr = std::make_shared<TestClass>(100, 200); // Process.... classPtr = std::make_shared<TestClass>(100, 200); return 0; }
我用新内存覆盖了已管理对象的shared_ptr。根据对shared_ptr赋值运算符的查阅,旧内存应在新赋值前销毁,预期输出为:
constructor destructor constructor destructor
但实际输出为:
constructor constructor destructor destructor
请问旧内存的状态如何,为何未在第二次分配前被释放?
问题解析
这是因为std::shared_ptr的赋值运算符首先会完成新对象的构造,再处理旧对象的引用计数与销毁逻辑。
具体执行流程:
- 执行
classPtr = std::make_shared<TestClass>(100, 200);时,先调用std::make_shared构造新的TestClass对象,输出第二个constructor; - 赋值运算符接管新的shared_ptr后,旧shared_ptr的引用计数减1——由于原
classPtr是唯一持有者,引用计数变为0,触发旧对象析构,输出第一个destructor; - 程序结束时,当前
classPtr管理的新对象离开作用域,引用计数清零,触发第二个destructor。
旧内存的状态是安全的:当引用计数降为0时,对象会被正确析构,内存也会被std::shared_ptr的管理机制释放,不存在内存泄漏。你预期的顺序不符合实际,是因为新对象的构造操作发生在旧对象销毁之前。
补充说明
如果想要实现“先销毁旧对象,再构造新对象”的顺序,可以拆分操作:
classPtr.reset(); // 手动重置,先销毁旧对象 classPtr = std::make_shared<TestClass>(100, 200); // 再构造新对象
此时输出会符合你的预期:
constructor destructor constructor destructor
内容的提问来源于stack exchange,提问作者Nitron_707
相关产品推荐
相关产品推荐

