当前位置: 首页 > news >正文

C++ 智能指针实现原理

C++ 智能指针是通过 RAII(资源获取即初始化)技术来管理动态分配内存的工具,它能避免手动管理内存时常见的内存泄漏问题。下面详细介绍其两大核心机制:引用计数和自定义删除器。

一、 引用计数原理

引用计数是智能指针实现资源自动释放的基础机制。其工作流程如下:

  1. 当一个智能指针被创建并指向某个资源时,该资源的引用计数初始化为 1。
  2. 当智能指针被复制(如赋值给其他智能指针)或作为参数传递时,引用计数加 1。
  3. 当智能指针被销毁(如离开作用域)或被重置为指向其他资源时,引用计数减 1。
  4. 当引用计数降为 0 时,表示没有智能指针再引用该资源,此时自动释放该资源。

这种机制确保了资源的生命周期与引用它的智能指针数量严格绑定。C++ 标准库中的 std::shared_ptrstd::weak_ptr 就是基于引用计数实现的。

二、自定义删除器

默认情况下,智能指针在引用计数为 0 时会使用 delete 操作符释放资源。但对于一些特殊资源,如文件句柄、网络连接等,需要自定义释放方式,这时就可以使用自定义删除器。自定义删除器允许用户指定一个可调用对象(函数、函数对象或 Lambda 表达式),在资源释放时调用该对象来执行特定的清理操作。

三、 示例代码

下面是一个简单的示例,展示了引用计数和自定义删除器的用法:

#include <iostream>
#include <memory>// 自定义资源类,用于演示
class Resource {
public:Resource(int id) : id_(id) {std::cout << "Resource " << id_ << " created" << std::endl;}~Resource() {std::cout << "Resource " << id_ << " destroyed" << std::endl;}void use() const {std::cout << "Using resource " << id_ << std::endl;}
private:int id_;
};// 自定义删除器函数
void customDeleter(Resource* res) {std::cout << "Custom deleting resource" << std::endl;delete res;
}int main() {// 创建一个 shared_ptr,使用自定义删除器std::shared_ptr<Resource> ptr1(new Resource(1), customDeleter);std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;// 复制 shared_ptr,引用计数增加std::shared_ptr<Resource> ptr2 = ptr1;std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;std::cout << "ptr2 use count: " << ptr2.use_count() << std::endl;// 使用资源ptr1->use();ptr2->use();// 重置 ptr2,引用计数减少ptr2.reset();std::cout << "After reset ptr2:" << std::endl;std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;// ptr1 离开作用域,引用计数变为 0,资源被释放return 0;
}

四、代码解释

  1. 引用计数演示

    • ptr1 创建时引用计数为 1。
    • ptr2 复制 ptr1 后,两者引用计数都变为 2。
    • ptr2.reset() 使 ptr2 不再引用资源,ptr1 的引用计数变回 1。
    • ptr1 离开作用域时,引用计数降为 0,资源被释放。
  2. 自定义删除器演示

    • 通过 std::shared_ptr 的第二个参数传入 customDeleter 函数。
    • 当资源释放时,会先调用 customDeleter 函数,再执行实际的资源释放操作。

通过这种方式,C++ 智能指针提供了一种安全且灵活的内存管理方式,既能自动管理资源生命周期,又能适应各种特殊资源的释放需求。

相关文章:

  • 香橙派3B学习笔记9:Linux基础gcc/g++编译__C/C++中动态链接库(.so)的编译与使用
  • Mybatisplus3.5.6,用String处理数据库列为JSONB字段
  • 【CF】Day80——Codeforces Round 872 (Div. 2) C⭐D (思维 + 模拟 | 树 + 思维 + 组合数学 + 分数取模)
  • 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
  • 【valse2025】CV与ML领域重要进展
  • python打卡训练营打卡记录day50
  • 【Java工程师面试全攻略】Day7:分布式系统设计面试精要
  • 蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
  • 聊聊 Pulsar:Producer 源码解析
  • python打卡day50
  • 常见的http状态码
  • 重温经典算法——二分查找
  • Word中如何对文献应用的格式数字连起来,如:【1-3】
  • 【SQL学习笔记3】深入理解窗口函数的用法
  • Java SE - 数组
  • svg预览器
  • 嵌入式学习Day35
  • Debian系统简介
  • 今日行情明日机会——20250610
  • 【WiFi扫描相关帧】
  • 电商网站建设的现实意义是什么/网站收录查询工具
  • 如何申请网站空间和注册域名/软文撰写案例
  • 营销型网站有那些网站/江北seo综合优化外包
  • 做音乐分享的网站/aso优化师
  • 营销网站建设哪家便宜/营销软文推广平台
  • 如何做网站内页排名/atp最新排名