shared_ptr
约 569 字大约 2 分钟
C++11智能指针内存管理
2026-05-20
shared_ptr 是 C++11 提供的共享所有权智能指针。它的核心目标不是“让指针更好看”,而是把对象生命周期交给引用计数管理,避免手写 delete 时常见的遗漏和重复释放问题。
它解决的是什么问题
如果一个对象会被多个地方同时持有,那么只靠裸指针很难说清楚“到底谁负责释放”。一旦约定不清晰,就容易出现两类问题:
- 没人释放,造成内存泄漏
- 多处重复释放,导致未定义行为
shared_ptr 的做法是把“对象本身”和“控制块”分开。控制块里维护引用计数,只要最后一个 shared_ptr 被销毁,对象才会真正释放。
最基本的使用方式
#include <iostream>
#include <memory>
struct Connection {
Connection() {
std::cout << "open\n";
}
~Connection() {
std::cout << "close\n";
}
};
int main() {
auto connection = std::make_shared<Connection>();
auto backup = connection;
std::cout << connection.use_count() << '\n';
}这里的 connection 和 backup 共享同一个 Connection 实例。两者都离开作用域后,析构函数才会执行。
推荐优先使用 make_shared
通常不要直接写:
std::shared_ptr<Foo> ptr(new Foo());更推荐这样写:
auto ptr = std::make_shared<Foo>();原因很直接:
- 写法更短
- 对象和控制块通常可以一次分配
- 异常安全更好
使用时最容易踩的坑
最常见的问题不是“不会用”,而是“到处都用”。shared_ptr 表达的是共享所有权,如果对象的拥有关系其实非常明确,就不应该为了省事把所有东西都包成 shared_ptr。
另外要注意循环引用。例如 A 持有 B 的 shared_ptr,B 又持有 A 的 shared_ptr,那么引用计数永远不会归零,这时就需要 weak_ptr 打断环。
什么时候适合使用
下面这些场景更适合 shared_ptr:
- 一个对象确实会被多个模块共同持有
- 生命周期无法由单一所有者清晰表达
- 你需要把对象安全地传给异步任务或回调
如果所有权非常明确,优先考虑 unique_ptr;如果只是临时观察对象,不应该额外增加所有权,就考虑 weak_ptr 或裸引用。
