You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中覆盖shared_ptr指向对象时旧内存未提前释放的原因

关于std::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的赋值运算符首先会完成新对象的构造,再处理旧对象的引用计数与销毁逻辑。

具体执行流程:

  1. 执行classPtr = std::make_shared<TestClass>(100, 200);时,先调用std::make_shared构造新的TestClass对象,输出第二个constructor;
  2. 赋值运算符接管新的shared_ptr后,旧shared_ptr的引用计数减1——由于原classPtr是唯一持有者,引用计数变为0,触发旧对象析构,输出第一个destructor;
  3. 程序结束时,当前classPtr管理的新对象离开作用域,引用计数清零,触发第二个destructor。

旧内存的状态是安全的:当引用计数降为0时,对象会被正确析构,内存也会被std::shared_ptr的管理机制释放,不存在内存泄漏。你预期的顺序不符合实际,是因为新对象的构造操作发生在旧对象销毁之前。

补充说明

如果想要实现“先销毁旧对象,再构造新对象”的顺序,可以拆分操作:

classPtr.reset(); // 手动重置,先销毁旧对象
classPtr = std::make_shared<TestClass>(100, 200); // 再构造新对象

此时输出会符合你的预期:

constructor
destructor
constructor
destructor

内容的提问来源于stack exchange,提问作者Nitron_707

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:57:07