new 出来的对象谁负责 delete,团队项目里吵过无数次,C++11 之后的答案交给智能指针。shared_ptr 在 memory 头文件里,本质是带引用计数的指针:多处代码可以同时持有,最后一个持有者销毁时自动释放内存。

基本用法

#include <memory>
std::shared_ptr<int> p = std::make_shared<int>(42);
std::cout << *p;   // 输出 42

创建优先用 make_shared,对象和控制块一次分配完成,比先 new 再构造省一次内存操作。拷贝一份,引用计数加一,指针出作用域计数减一,减到零就析构对象。它支持解引用和箭头访问成员,能当布尔值判断是否为空,两个指针指向同一对象时用 == 比较相等。

三个最常见的坑

  • 循环引用:两个对象各持一个 shared_ptr 指向对方,计数永远降不到零,内存就漏了。办法是其中一端换成 weak_ptr,只观察不持有
  • 用同一个裸指针初始化多个智能指针,等于两套计数各管各的,析构时重复释放直接崩溃。一个对象从头到尾只让一组智能指针管
  • 引用计数本身的增减是原子操作,多线程下安全,但它指向的对象该加锁还得加锁

进阶一点的细节

  • get() 返回的是裸指针,只能临时传给老接口用,拿它去 delete 或者再包一层智能指针,计数就乱了
  • 构造时可以传自定义删除器,管文件句柄、数据库连接这类资源也适用
  • make_shared 把对象和控制块放在同一块内存,只要还有 weak_ptr 观察着,这块内存就整体不释放,超大对象要掂量

什么时候不该用?对象生命周期唯一且明确时,unique_ptr 更轻更快;shared_ptr 解决的是共享所有权,多处持有、谁也说不准活到最后的场景才轮到它。一句话判断:能用 unique_ptr 就别上计数,需要共享再上。