shared_ptr解决多对象共享堆内存时的手动管理难题,通过引用计数自动释放资源;每个实例绑定控制块记录引用数,拷贝增、析构减,归零时delete;须避免裸指针重复构造,推荐make_shared或拷贝创建。

shared_ptr 解决什么问题
手动管理动态内存时,new 和 delete 容易配对失败,导致内存泄漏或重复释放。当多个对象或函数需要共享同一块堆内存(比如一个数据结构被多个模块读写),用裸指针根本无法安全判断“现在还能不能删”。shared_ptr 就是为这种场景设计的:它把“谁还在用这块内存”这个信息显式记录下来,靠引用计数自动决定何时释放。
引用计数怎么工作的
每个 shared_ptr 实例背后绑着一个控制块(control block),里面存着指向实际对象的指针和一个引用计数。每次拷贝构造、赋值或作为参数传入,计数加 1;超出作用域、重置或被赋值为另一个 shared_ptr 时,计数减 1。计数归零,控制块才调用 delete 销毁对象。
注意:两个指向同一地址的 shared_ptr 必须由同一个原始 shared_ptr 派生,否则控制块不共享,会 double-delete:
int* raw = new int(42); std::shared_ptra(raw); // ❌ 危险!a 独占控制块 std::shared_ptr b(raw); // ❌ b 另建控制块 → 后续析构两次 delete raw
正确做法是始终用 std::make_shared 构造,或通过拷贝已有 shared_ptr:
立即学习“C++免费学习笔记(深入)”;
一个功能强大、性能卓越的企业建站系统。使用静态网页技术大大减轻了服务器负担、加快网页的显示速度、提高搜索引擎推广效果。本系统的特点自定义模块多样化、速度快、占用服务器资源小、扩展性强,能方便快捷地建立您的企业展示平台。简便高效的管理操作从用户使用的角度考虑,对功能的操作方便性进行了设计改造。使用户管理的工作量减小。网站互动数据可导出Word文档,邮件同步发送功能可将互动信息推送到指定邮箱,加快企业
auto a = std::make_shared(42); // ✅ 推荐 auto b = a; // ✅ 共享同一控制块
和 unique_ptr、weak_ptr 的关键区别
unique_ptr 是独占语义:不可拷贝,只能移动,适合“我管到底”的场景;shared_ptr 是共享语义:可拷贝,但有运行时开销(控制块内存 + 原子计数);weak_ptr 不增加引用计数,只用于打破循环引用 —— 比如父子节点互相持有 shared_ptr,就会导致计数永远不归零。
- 性能敏感且所有权明确?优先选
unique_ptr - 需要多处共享且生命周期不确定?用
shared_ptr - 共享中还要观察对象是否还活着(比如缓存、监听器列表)?配合
weak_ptr::lock()使用
容易踩的坑
常见错误不是语法问题,而是语义误用:
- 把裸指针传给多个
shared_ptr构造函数 → double-delete - 在类成员里用
shared_ptr持有this(比如异步回调里保存shared_from_this()),但忘了该类必须继承自std::enable_shared_from_this - 在循环引用场景下没引入
weak_ptr,导致内存永远不释放 - 误以为
shared_ptr能管理栈对象或全局对象 —— 它只应配合堆分配(new或make_shared)
引用计数本身是线程安全的(增减原子),但所指对象的访问仍需额外同步 —— 这点常被忽略。








