c++如何实现简单的垃圾回收机制_c++ 引用计数与自动内存管理策略【教程】


C++标准不提供垃圾回收,引用计数(如std::shared_ptr)仅为RAII式确定性释放,并非真正GC;它无法解决循环引用、无堆扫描能力、有性能开销且不管理非new内存或非内存资源。

C++ 标准本身不提供垃圾回收(GC),但可以用引用计数实现类 GC 的自动内存管理效果——关键在于:它不是真正的 GC,而是确定性、可预测的资源释放;用错场景反而会引发循环引用或性能问题。

为什么不能直接用 std::shared_ptr 当“垃圾回收器”

std::shared_ptr 是引用计数智能指针,但它不解决循环引用,也不扫描堆内存。它只是在引用数归零时立即调用 delete,属于 RAII 范畴,不是 GC。

  • 循环引用时,两个对象互相持有 shared_ptr,引用计数永不为 0,内存泄漏
  • 频繁拷贝 shared_ptr 会带来原子操作开销(尤其在多线程下)
  • 无法回收原始裸指针、malloc 分配的内存、或非 new 构造的对象
  • 不处理栈对象、全局对象、或文件句柄等非内存资源(除非你自定义 deleter)

手动实现轻量引用计数类的关键点

自己写一个最小可用的引用计数指针,能帮你理解底层逻辑,也便于定制行为(比如日志、调试计数、弱引用支持)。

template
class RefCountPtr {
    T* ptr_;
    size_t* count_;
void release() {
    if (count_ && --(*count_) == 0) {
        delete ptr_;
        delete count_;
    }
}

public: explicit RefCountPtr(T* p = nullptr) : ptr(p), count(p ? new size_t(1) : nullptr) {}

RefCountPtr(const RefCountPtr& other) : ptr_(other.ptr_), count_(other.count_) {
    if (count_) ++(*count_);
}

RefCountPtr& operator=(const RefCountPtr& other) {
    if (this != &other) {
        release();
        ptr_ = other.ptr_;
        count_ = other.count_;
        if (count_) ++(*count_);
    }
    return *this;
}

~RefCountPtr() { release(); }

T& operator*() const { return *ptr_; }
T* operator-youjiankuohaophpcn() const { return ptr_; }

};

  • 必须用 size_t* 单独分配计数器,不能和对象布局耦合(否则无法通用)
  • 拷贝构造/赋值中要判空,避免对 nullptr 解引用或递增空指针
  • 析构时只负责释放计数器和对象,不负责重置 ptr_(这是安全的,因对象已销毁)
  • 没实现 weak_ptr 等价物,所以仍无法破循环引用

如何检测和打破循环引用

循环引用不是语法错误,运行期才暴露为内存泄漏。靠工具或设计约束来预防更实际。

  • std::weak_ptr 替代部分 shared_ptr:比如观察者模式中,被观察者持 shared_ptr,而观察者内部用 weak_ptr 回调
  • 静态分析:Clang 的 -Wlifetime 可捕获部分悬垂引用,但对跨对象循环无能为力
  • 运行时调试:重载 operator new + 全局计数器,配合 atexit() 检查未释放对象数量
  • 设计上规避:用 ID 或句柄(int)代替裸指针/智能指针传递,由中心容器管理生命周期

什么场景下真该考虑外部 GC(如 Boehm GC)

只有当你明确需要“不可预测但自动”的回收语义,且能接受限制时,才引入第三方 GC。

  • 嵌入脚本解释器(如用 C++ 实现 Lua host),需托管脚本对象生命周期
  • 遗留代码大量使用 malloc/free,又不愿重构为 RAII
  • 算法原型阶段,优先保证逻辑正确,暂不优化内存路径

Boehm GC 是保守式 GC,它可能把栈上一个整数误认为指针,从而漏回收真实对象;它不调用析构函数,所以不能用于管理含资源(文件、锁、GPU buffer)的对象——这点常被忽略。


# 工具  #   # ai  # c++  # 垃圾回收器  # 为什么  # red  # lua  # count  # 析构函数  # int  # 循环  # 指针  #   # public  # operator  # 线程  # 多线程  # 空指针  # delete  # 对象  # 算法  # 重构  # 句柄  # 或非  # 这是  # 也不  # 是在  # 零时  # 可以用  # 当你  # 帮你  # 仅为 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: c++怎么设置线程优先级与cpu亲和性_c++ 多核处理器性能绑定【指南】  如何使用Golang匿名函数_快速定义临时函数逻辑  Win11屏幕亮度突然变暗怎么解决_自动变暗问题处理  Win11输入法选字框不见了怎么办_Win11输入法修复与重置【教程】  Windows10无法识别USB设备描述符请求失败_通用串行总线控制器修复  如何在Golang中引入测试模块_Golang测试包导入与使用实践  php打包exe后无法写入文件_权限问题解决方法【教程】  如何减少Golang内存碎片化_Golang内存分配与回收优化方法  Linux如何申请SSL免费证书_Linux下Certbot安装与Nginx自动续期【指南】  Windows10如何查看蓝屏日志_Win10使用事件查看器分析Dump文件  windows 10应用商店区域怎么改_windows 10微软商店切换地区方法  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询  Windows10蓝屏代码DPC_WATCHDOG_VIOLATION_Win10死机修复指南  Win10怎样卸载DockerDesktop_Win10卸载DockerDesktop步骤【步骤】  如何在 ACF 中正确更新嵌套多层 Group 字段内的子字段  MAC怎么在照片中添加水印_MAC自带编辑工具文字水印叠加【方法】  php修改数据怎么批量改状态_批量更新status字段值技巧【操作】  C++如何编写函数模板?(泛型编程入门)  Win11怎么设置默认邮件客户端 Win11修改Mail应用关联【教程】  c++如何用AFL++进行模糊测试 c++ Fuzzing入门【安全】  Win11怎么开启上帝模式_创建Windows 11 God Mode全能文件夹【技巧】  如何在 Python 测试中动态配置 @backoff 装饰器的重试次数  Linux怎么实现内网穿透_Linux安装Frp客户端与服务端配置【方法】  Win11怎样彻底卸载自带应用_Win11彻底卸载自带应用方法【步骤】  Win11怎么设置默认PDF阅读器 Win11修改PDF打开方式【步骤】  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  Go 中 defer 语句在 goroutine 内部不返回时不会执行  php订单日志怎么按金额排序_php按订单金额排序日志方法【方法】  Python深度学习实战教程_神经网络模型构建与训练  如何高效获取循环末次生成的 NumPy 数组最后一个元素(无需额外循环)  c++协程和线程的区别 c++异步编程模型对比【核心】  如何在 Go 项目开发中正确处理本地包导入与远程模块路径的一致性问题  Win11如何设置环境变量 Win11添加和修改系统与用户变量【教程】  如何使用Golang实现文件加密_Golang crypto 文件加密示例  C++如何使用std::async进行异步编程?(future用法)  如何在Golang中处理云原生事件_使用Event和Notification机制  如何在 Python 中将 ISO 8601 时间戳转换为日期并计算日期差值  Mac系统更新下载慢或失败怎么办_解决macOS升级问题【方法】  Go 中 defer 在 goroutine 内部不生效的原因与执行时机详解  php怎么连接数据库_MySQL数据库连接的基础代码编写【说明】  Win11怎么退出微软账户_切换Win11为本地账户登录方法【详解】  Win11如何开启telnet服务 Win11启用Telnet客户端【步骤】  Win11怎么设置右键刷新选项_Windows11显示更多选项技巧  如何优化Golang内存分配与GC调度_Golang垃圾回收优化示例  如何用::实现工具类方法调用_php静态工具类设计技巧【技巧】  Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】  php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】  Win11怎么开启HDR模式_Windows 11高动态范围显示设置指南【详解】  Windows10系统怎么查看防火墙状态_Win10安全中心网络保护 

 2026-01-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.