RAII简介

📦 一、技术原理简介:RAII是个“托管狂魔”

想象你有个健忘的朋友,每次借东西都会忘记归还。RAII(Resource Acquisition Is Initialization,资源获取即初始化)就是C++派来的“超级管家”:

“你负责借,我负责还!”

核心逻辑

  1. 出生即打工:对象在构造函数里获取资源(内存、文件、锁等)。
  2. 去世前还债:对象在析构函数里自动释放资源。
  3. 死也要还:即使程序中途崩溃(如抛异常),对象死前也会调用析构函数清理资源!

👉 本质资源的命,就是对象的命! 对象活着,资源有效;对象去世,资源释放。


🔍 二、核心功能解析:RAII的三大绝招

1️⃣ 自动释放:告别手动delete/close

传统代码像总忘记关冰箱门:

void riskyFile()
{FILE* file = fopen("data.txt", "r"); // 借冰箱readData(file); // 用冰箱// 如果这里抛异常?冰箱门永远开着!fclose(file); // 可能忘关!
}

RAII版:冰箱门自动关!

class FileHandler {
public:FileHandler(const string& path) {fileHandle = fopen(path.c_str(), "r"); 	// 出生即开门}~FileHandler() { if (fileHandle) fclose(fileHandle); 	// 死前必关门}
private:FILE* fileHandle = nullptr;
};void safeFile() {FileHandler fridge("data.txt"); // 开门throw "Oops! 冰箱炸了!"; 
} // 即使爆炸,析构也会关门! [1,3](@ref)

2️⃣ 异常安全:崩溃也不留烂摊子

C++规定:抛异常时,所有活着的对象必须“死前清理”(栈展开调用析构函数)。

void doJob() {std::lock_guard<std::mutex> lock(mutex); // 出生即锁门throw "程序崩了!"; 
} // 即使崩了,lock析构时自动解锁![7](@ref)

3️⃣ 禁止拷贝,支持移动:资源只能有一个爹

RAII对象默认“独占资源”(如文件句柄只能被一个对象管理)。想转让资源?用移动语义

class Socket {
public:Socket() { /* 抢资源 */ }~Socket() { /* 释放资源 */ }// 禁用拷贝(防止多个对象抢同一资源)Socket(const Socket&) = delete;// 支持移动(资源过户)Socket(Socket&& other) noexcept { resource = other.resource;other.resource = nullptr; // 原对象变穷光蛋}
};

🧪 三、基础代码示例:手搓一个RAII类

需求:管理一段临时内存(比如缓存区)

class MemoryPool {
public:// 1. 构造即抢资源MemoryPool(size_t size) : buffer(new char[size]) {cout << "抢到" << size << "字节内存!" << endl;}// 2. 析构必释放~MemoryPool() noexcept {delete[] buffer;cout << "释放内存!绝不赖账!" << endl;}// 3. 禁用拷贝(避免重复释放)MemoryPool(const MemoryPool&) = delete;MemoryPool& operator=(const MemoryPool&) = delete;// 4. 支持移动(资源过户)MemoryPool(MemoryPool&& other) noexcept : buffer(other.buffer) {other.buffer = nullptr; // 原对象变穷光蛋}char* get() const { return buffer; }private:char* buffer;
};// 使用示例
void processData() {MemoryPool pool(1024); // 申请1KB缓存loadData(pool.get()); 
} // 函数结束 → pool去世 → 自动释放内存![5,7](@ref)

🚀 四、应用场景举例:RAII在C++中的“全家桶”

资源类型RAII封装工具功能
动态内存std::unique_ptr自动delete,防内存泄漏
文件句柄std::fstream自动打开关闭文件
互斥锁std::lock_guard作用域结束自动解锁,防死锁
网络连接自定义Socket异常时自动断开连接
数据库连接连接池 + shared_ptr引用计数为0时自动归还连接

智能指针实战

void safeMemory() {auto ptr = std::make_unique<int>(42); // 构造即抢内存throw "内存溢出?无所谓!"; 
} // ptr析构 → 自动delete!稳如老狗

锁管理实战

std::mutex mtx;
void safeWithdraw() {std::lock_guard<std::mutex> lock(mtx); // 加锁withdrawMoney(); // 任意操作
} // 函数结束 → lock析构 → 自动解锁!防死锁

⚖️ 五、优势对比:RAII vs 手动管理

对比项RAII手动管理结果
资源释放自动(析构函数调用)需手动delete/closeRAII防漏
异常安全性✅ 强保证(析构必执行)❌ 脆弱(异常路径易漏释放)RAII更可靠
代码复杂度逻辑内聚,代码简洁释放代码分散,重复书写RAII更易维护
多资源管理成员按声明逆序析构,自动协调需手动控制释放顺序RAII更安全
程序员负担只需记住:对象活着=资源有效时刻惦记“借了要还”RAII解放大脑!

经典翻车现场(手动管理)

void manualFile() {FILE* f = fopen("data.txt", "r");if (!check(f)) return; // 直接return?文件没关!parse(f); fclose(f); // 可能永远执行不到
}

💎 总结:为什么C++程序员爱死RAII?

  1. 懒人福音:资源获取释放全自动化,告别new/delete噩梦。
  2. 异常克星:程序崩了也不留资源烂摊子。
  3. 代码美容师:业务逻辑和资源管理分离,代码更清爽。

记住RAII三字诀:
​“出生抢,死前还,异常崩了也不欠!”​

下次写C++时,请对你的RAII对象说:

“好好打工,死前记得还债!” 😉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87333.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序入门实例_____打造你的专属单词速记小程序

上次通过天气查询小程序&#xff0c;我们初探了微信小程序开发的世界。这次&#xff0c;咱们再挑战一个有趣又实用的项目 ——“单词速记小程序”。无论是学生党备考&#xff0c;还是上班族提升英语&#xff0c;都能用得上&#xff01;接下来就跟着我&#xff0c;一步一步把它做…

gateway白名单存储nacos,改成存储数据库

前言 很久没写博客了&#xff0c;csdn都开始ai润色了&#xff0c;之前都是看相应框架的源码看了个遍&#xff0c;感觉底层原理都差不多&#xff0c;这阵子着手改造了下gateway中的白名单&#xff0c;之前白名单存储到nacos&#xff0c;要改成存到数据库。里面涉及到浅浅的源码…

ubentu服务器版本安装Dify

Docker 中安装Dify 首先安装Docker 1. 克隆Dify代码仓库 从github克隆 Dify 源代码至要本地环境。 我的ubentu服务器版本&#xff0c;我把源代码下载到 /var/下 在var文件夹下执行 git clone https://github.com/langgenius/dify.git执行成功后&#xff0c;进入Dify源代码的…

Redis分布式锁实战:从入门到生产级方案

目录 一、为什么需要分布式锁&#xff1f; 二、Redis分布式锁核心特性 三、实现方案与代码详解 方案1&#xff1a;基础版 SETNX EXPIRE 原理 代码示例 问题 方案2&#xff1a;Redisson框架&#xff08;生产推荐&#xff09; 核心特性 代码示例 优势 方案3&#xff…

【Redis】StringRedisTemplate 和 RedisTemplate 的区别

StringRedisTemplate 和 RedisTemplate 是 Spring Data Redis 提供的两种用于操作 Redis 的模板类&#xff0c;它们的核心区别在于 序列化方式 和 操作的数据类型。以下是两者的主要区别和使用建议&#xff1a; ✅ 1. 数据类型支持 类名支持的数据类型说明RedisTemplate支持所…

docker-compose快速搭建redis集群

目录结构 redis-cluster/ ├── config/ │ ├── master.conf │ ├── slave1.conf │ └── slave2.conf └── docker-compose.yml配置文件内容 1. config/master.conf # Redis主节点配置 port 6379 bind 0.0.0.0 protected-mode no logfile "redis-mas…

SpringCloud系列(39)--SpringCloud Gateway常用的Route Predicate

前言&#xff1a;在上一节中我们实现了SpringCloud Gateway的动态路由 &#xff0c;而在本节中我们将着重介绍各种Route Predicate的作用。 1、可以到官方文档里查看常用的Route Predicate的种类 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.REL…

渐变色的进度条控件

近日&#xff0c;用VB.net2003重写了一个渐变色的进度条控件。主要有以下功能&#xff1a; 支持自定义进度条分段数量&#xff0c;可拆分为多个步骤&#xff1b;每个步骤可独立显示完成百分比及渐变色效果。 每个步骤均可配置任务名称和描述&#xff1b;运行时能实时显示当前执…

【DICOM后处理】qt+vs 实现DICOM数据四视图显示

目录 1、DICOM四视图2、vtkImageViewer2 实现二维平面图显示3、vtkVolume实现三维体数据显示4、实现界面图 1、DICOM四视图 DICOM四视图通常指同时显示医学影像的四个不同平面或视角&#xff0c;用于全面分析三维数据&#xff08;如CT、MRI等&#xff09;。 标准四视图布局&a…

Google Maps 安装使用教程

一、Google Maps 简介 Google Maps 是谷歌提供的地图服务&#xff0c;通过其 JavaScript API&#xff0c;开发者可以在网页中嵌入地图&#xff0c;添加标记、路径、地理编码、路线导航等功能&#xff0c;适用于位置展示、物流追踪、LBS 应用等场景。 二、获取 Google Maps API…

Nginx+Keepalived实现前台服务高可用

现阶段项目开发往往采用前后台分离&#xff0c;前台常用的技术有vue、react等&#xff0c;前台代码部署在nginx中&#xff0c;代码中配置了后台服务的网关地址&#xff0c;由网关向后台分发服务请求&#xff0c;架构示意图如下&#xff1a; 在上述架构图中&#xff0c;如果Ngin…

Gradio全解13——MCP协议详解(5)——Python包命令:uv与uvx实战

Gradio全解13——MCP协议详解&#xff08;5&#xff09;——Python包命令&#xff1a;uv与uvx实战 第13章 MCP协议详解13.5 Python包命令&#xff1a;uv与uvx实战13.5.1 uv核心亮点与常用命令1. uv介绍2. 安装与项目管理3. 脚本与工具4. Python版本与pip接口 13.5.2 uv核心指令…

OD 算法题 B卷【求最小步数】

文章目录 求最小步数 求最小步数 求从坐标零点到坐标点n的最小步数&#xff0c;一次只能沿着横坐标轴向左或向右移动2或3&#xff1b;途经的坐标点可以为负数&#xff1b; 输入描述: 坐标点n 输出描述: 从坐标零点移动到坐标点n的最小步数 n在【1,10^9】 示例1 输入&#xf…

Elasticsearch 集群升级实战指引—7.x 升级到 8.x

升级Elasticsearch集群从7.x到8.x是一项复杂且关键的任务&#xff0c;涉及重大版本变更&#xff08;如API调整、配置变更、安全功能强制启用等&#xff09;&#xff0c;可能影响集群的性能和稳定性。结合您提到的业务量增长导致索引写入变慢的问题&#xff0c;本指引不仅提供详…

JWT学习总结

文章目录 前置知识Authorization头部和 CookieCRSF攻击 JWT概念JWT认证流程使用Springboot整合JWTJwtUtil JWT案例控制器JWT拦截器注册拦截器结果 session VS Jwt 前置知识 Authorization头部和 Cookie Authorization 头部和 Cookie 是 HTTP 协议中两种不同的身份认证 / 信息…

阿里云消息队列 Apache RocketMQ 创新论文入选顶会 ACM FSE 2025

近日&#xff0c;由阿里云消息团队发表的 Apache RocketMQ 创新论文被 CCF-A 类软件工程顶级会议 FSE 2025 Industry Track 录用。 ACM FSE&#xff08;The ACM International Conference on the Foundations of Software Engineering&#xff09;是享有盛誉的国际学术会议&…

定制WordPress管理后台

WordPress作为全球最流行的建站工具&#xff0c;因其灵活性和易用性受到广泛欢迎。许多服务器提供商都支持一键安装WordPress&#xff0c;例如Hostease&#xff0c;使新手用户也能轻松搭建属于自己的网站。然而&#xff0c;后台的默认设置可能无法完全满足不同用户的需求。定制…

REST API设计与Swagger:构建高效、易用的Web服务

引言 在现代Web开发中&#xff0c;REST API已成为不同系统间通信的标准方式。一个设计良好的REST API不仅能提高开发效率&#xff0c;还能改善用户体验。而Swagger&#xff08;现称为OpenAPI&#xff09;作为API文档和测试的强大工具&#xff0c;已经成为API开发中不可或缺的一…

一个非对齐访问的问题

1、引言 最近在编写代码时&#xff0c;出现了这样一个 bug。程序一跑&#xff0c;系统就崩溃了&#xff0c;报错是 bus error。 目标平台&#xff1a;ARM32 最终定位到出错的代码片段&#xff1a; *((uint32_t *)ptr) id;这里的 ptr 是一个非 4 字节对齐的地址&#xff01;&a…

【构造】P8976 「DTOI-4」排列|普及+

本文涉及知识点 构造 P8976 「DTOI-4」排列 题目背景 Update on 2023.2.1&#xff1a;新增一组针对 yuanjiabao 的 Hack 数据&#xff0c;放置于 #21。 Update on 2023.2.2&#xff1a;新增一组针对 CourtesyWei 和 bizhidaojiaosha 的 Hack 数据&#xff0c;放置于 #22。…