C++智能指针shared_ptr的作用?(自动管理内存引用计数)

11次阅读

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

C++智能指针shared_ptr的作用?(自动管理内存引用计数)

shared_ptr 解决什么问题

手动管理动态内存时,newdelete 容易配对失败,导致内存泄漏或重复释放。当多个对象或函数需要共享同一块堆内存(比如一个数据结构被多个模块读写),用裸指针根本无法安全判断“现在还能不能删”。shared_ptr 就是为这种场景设计的:它把“谁还在用这块内存”这个信息显式记录下来,靠引用计数自动决定何时释放。

引用计数怎么工作的

每个 shared_ptr 实例背后绑着一个控制块(control block),里面存着指向实际对象的指针和一个引用计数。每次拷贝构造、赋值或作为参数传入,计数加 1;超出作用域、重置或被赋值为另一个 shared_ptr 时,计数减 1。计数归零,控制块才调用 delete 销毁对象。

注意:两个指向同一地址的 shared_ptr 必须由同一个原始 shared_ptr 派生,否则控制块不共享,会 double-delete:

int* raw = new int(42); std::shared_ptr a(raw);  // ❌ 危险!a 独占控制块 std::shared_ptr b(raw);  // ❌ b 另建控制块 → 后续析构两次 delete raw

正确做法是始终用 std::make_shared 构造,或通过拷贝已有 shared_ptr

立即学习C++免费学习笔记(深入)”;

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 能管理对象或全局对象 —— 它只应配合堆分配(newmake_shared

引用计数本身是线程安全的(增减原子),但所指对象的访问仍需额外同步 —— 这点常被忽略。

text=ZqhQzanResources