讲师中心 微信公众号

工具推荐

视频效率加速
Laper
Laper

剧本策划到成片协作

AniShort
AniShort

AI短剧协同制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Seko
Seko

AI短剧一键生成成片

C++实现简单的智能指针 _ 引用计数与析构管理原理【源码】

陌伟酱_3589

陌伟酱_3589

发布时间:2026-04-10 22:31:35

|

341人浏览过

|

来源于php中文网

原创

必须将引用计数与托管对象分离并置于堆上control block中,使多个shared_ptr共享同一计数;否则各自计数导致释放逻辑错乱。

c++实现简单的智能指针 _ 引用计数与析构管理原理【源码】

自己实现一个能用的 std::shared_ptr 简化版,核心不在“多线程安全”或“定制删除器”,而在搞清引用计数怎么和对象生命周期绑定——只要理解 control block 的存在必要性,就踩不到最深的坑。

为什么不能直接在智能指针对象里存引用计数?

因为多个 shared_ptr 可能指向同一块内存,但它们是独立对象。如果每个都存一份计数,++/-- 就完全不同步,析构时根本不知道该不该释放资源。

必须把引用计数(和可能的弱引用计数、自定义删除器)单独拎出来,放在堆上,让所有共享该资源的 shared_ptr 指向同一个 control block。

  • control block 通常和托管对象分配在同一块内存(或紧邻),但初版可分开 new,更清晰
  • 计数本身要用 int* 或 std::atomic_int*,普通 int 不行
  • 构造时:先 new control block,再 new 托管对象;析构时:先减强引用计数,为 0 则 delete 托管对象,再减控制块自身引用(为 0 则 delete control block)

shared_ptr 构造与拷贝时,control block 怎么共享?

拷贝构造/赋值不是浅拷贝指针,而是把原 shared_ptr 的 ptr_ 和 ctrl_ 都复制过来,然后对 ctrl_->strong_count 做原子加一。

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

关键点在于:ptr_ 是裸指针(指向托管对象),ctrl_ 是裸指针(指向 control block),两者解耦。这样即使 ptr_ 是 nullptr(空 shared_ptr),只要 ctrl_ 非空,也能管理计数逻辑。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 默认构造:两个指针都为 nullptr
  • 带参构造:ptr_ = new T{args...},ctrl_ = new control_block{1, 0, [](void* p){ delete static_cast<t>(p); }}</t>
  • 拷贝构造:仅复制 ptr_ 和 ctrl_,然后 ++ctrl_->strong_count
  • 移动构造:把原对象的 ptr_ 和 ctrl_ 移走,原对象置空,不操作计数

析构时 delete 的顺序和条件是什么?

析构只做两件事:减强引用计数,看是否归零;归零则触发资源释放 + 控制块释放。

注意:弱引用计数(weak_count)不影响托管对象生死,只影响 control block 自身是否可删。哪怕所有 shared_ptr 都没了,只要还有 weak_ptr 持有 ctrl_,control block 就不能 delete —— 否则 weak_ptr::lock() 会访问野指针。

  • 析构函数中:若 ctrl_ != nullptr,执行 --ctrl_->strong_count
  • 若 ctrl_->strong_count == 0,调用 ctrl_->deleter_(ptr_),再 --ctrl_->weak_count
  • 若此时 ctrl_->weak_count == 0,才 delete ctrl_
  • ptr_ 本身不 delete,它只是个观察者;释放动作由 deleter_ 决定(支持数组、自定义释放等)

最容易漏掉的边界情况:空指针和 reset() 的行为

reset() 不是简单地把 ptr_ 设为 nullptr,它本质是一次“析构 + 构造”:先按当前状态走一遍析构逻辑,再用新值重建(可能为空)。

空 shared_ptr(ptr_ == nullptr && ctrl_ == nullptr)是合法状态,但一旦你用它调用 reset(new T),就必须 new 出新的 control block;而如果 reset(nullptr),则要先完成旧资源清理,再清空自身指针。

  • 调用 reset() 前,需检查 ctrl_ 是否非空,决定是否走析构流程
  • reset(nullptr) 后,ptr_ 为 nullptr,ctrl_ 应为 nullptr(除非 weak_ptr 还活着,但此时本体已放弃管理权)
  • 重复 reset() 同一对象?不会 double-delete,因为每次 reset 都先析构旧状态

control block 的布局和生命周期管理,才是真正区分“能跑”和“真懂”的分水岭。很多人写到一半发现 weak_ptr 拿不到对象,或者多次 reset 后 crash,问题几乎全出在 control block 的 weak_count 更新时机和 delete 条件判断上。

热门AI工具

更多
SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7479

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3545

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4668

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

3125

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4668

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

904

2025.10.23

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

391

2025.11.27

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn