控制块在SharedPtr中的作用(C++)

一句话先给结论:

控制块(Control Block)是 shared_ptr 的“户口本”——它记录引用计数、托管对象指针、自定义删除器、自定义分配器以及 weak_ptr 的额外信息;所有指向同一对象的 shared_ptr / weak_ptr 共用同一份控制块,从而保证“最后一个离开的人关灯”。


1️⃣ 控制块里到底放了什么?

字段 作用
T* ptr 真正托管的裸指针
size_t shared_count 当前存活 shared_ptr 个数
size_t weak_count 当前存活 weak_ptr 个数
Deleter deleter 用户自定义删除器(默认为 delete
Allocator allocator 用户自定义分配器
可选额外信息 type-erased 的 deleter / allocator、控制块自身内存布局等


2️⃣ 生命周期规则(口诀版)

  1. shared_count == 0 → 销毁托管对象(调用 deleter)
  2. shared_count + weak_count == 0 → 销毁控制块(释放内存)

因此:

  • 只要还有 任意 shared_ptr,托管对象 不会 被销毁。
  • 只要还有 任意 weak_ptr,控制块 不会 被销毁(weak_ptr 要查过期状态)。

3️⃣ 一张时序图

make_shared<T>() ─┐
                  ├─► [Control Block: ptr=T*, shared=1, weak=0]
shared_ptr<T> p ──┘

shared_ptr<T> q = p;          // shared=2
weak_ptr<T>  w = p;           // weak=1
p.reset();                    // shared=1
q.reset();                    // shared=0 → 调用 deleter 销毁 T
w.expired();                  // 返回 false,weak=1 仍保活控制块
w.reset();                    // weak=0 → 销毁控制块

4️⃣ 与 make_shared / shared_ptr<T>(new T) 的细微差别

构造方式 控制块与对象内存布局
std::shared_ptr<T>(new T) 两次分配:先 new T,再 new ControlBlock → 可能 cache miss
std::make_shared<T>(...) 一次分配:一块连续内存里先放 T,再放 ControlBlock → 更快、省一次 new


5️⃣ 手写玩具代码回顾

template <typename T>
struct ControlBlock {
    T*       ptr;
    size_t   shared = 0;
    size_t   weak   = 0;
    /* optional deleter/allocator */
};

所有 SharedPtr<T> / WeakPtr<T> 拷贝时只改同一个 ControlBlock* 里的计数,对象与内存的“生死大权”全由控制块说了算。


✅ 一句话记住

控制块 = shared_ptr 的“中控室”;对象何时死、内存何时还,全看这间屋子里两个计数器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值