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

跟我学C++中级篇——RAII

一、什么是RAII

Resource Acquisition Is Initialization,资源获取即初始化。C/C++的开发者都知道,在这类语言的开发中,内存需要手动来控制。也就是说,释放和回收内存得开发者亲历亲为。从某种角度看,能够把控内存的细节,当然是更灵活,可如果把控的不好,却是一场灾难。
根据二八定律,对于绝大多数的开发者来说,都被划分到了灾难的一个方向(即使经验丰富技术高超的开发者也难免会出问题)。那么,尤如医学上所讲,预防大于治疗。在C++中,哪些对象的生命周期是不需要自己控制而由系统自动控制呢?很容易想到类的局部对象。c++之父Bjarne Stroustrup因此提出了上面的RAII,

二、作用

RAII的作用非常明显,就是管理资源。通过临时的对象自动调用析构函数来处理资源。既然这样,初始化资源就可以放到构造函数中,由开发者来进行控制并交由系统自动创建。而此处的资源很容易想到的就是内存。但其实不仅有内存还有相关的句柄、IO等等都可以。RAII其实可以显著的降低因为经验或者疏忽导致的资源泄露。
常见的RAII应用的场景有以下几种情况:
1、内存管理
2、锁管理
3、句柄管理
4、IO管理
5、其它
建议初学者一定要掌握这个技巧,则可以大幅的提高在开发过程中资源管理的安全性。RAII当然也有一些不足之处,最典型的缺点就是其的优势。假如一个资源只使用一下便可以回收。那么封装进入一个对象后,则其生命周期则升级到了这个对象的作用域生命周期。而且有可能无意间的循环引用和对象与资源生命周期的不同情况下,都可能会有一些细节的问题需要完善。

三、与三五原则的关系

在RAII中有一个比较典型的错误应用,它一般类似于下面的样子:

class Lock
{
public:Lock(){//相关锁初始化 }~Lock(){//相关锁回收}private://Lock(const Lock &);//Lock operator =(const Lock &);
};void UseLock(Lock l)//注意此处
{
//此处使用Lock来控制锁
}
unsigned  ThreadFun(){Lock l;UseLock(l);
}  

RAII如果类似上面的方法使用,即在RAII应用时再增加一层控制,发现锁就不好使了。难道RAII不能再封装?并不是,而是锁没有被深拷贝导致的UseLock函数中的复制的l并没有被拷贝出一个相同的副本,值传递导致在UseLock后其内部的l副本和ThreadFun中使用l共用一个锁资源。而前者在函数退出后会调用析构函数释放掉锁。这样在后面的Lock对象再使用形同虚设。在前面分析过三五原则,这个错误其实就是没有正确处理这个原则的非常典型的应用。

四、应用和例程

RAII的应用非常简单,就是以下几个步骤:
1、设计并开发一个类来封装相关的资源
2、在类构造函数中创建资源
3、在类的析构函数中释放资源
4、在实际的作用域空间内创建此类的临时对象
下面就看一个简单的锁的例子:

template <typename Mutex_> class lock_guard final {
public:lock_guard(Mutex_ *m_rwMt) : m_mt(m_rwMt) { pthread_mutex_lock(m_mt); }~lock_guard() { pthread_mutex_unlock(m_mt); }public:lock_guard(const lock_guard &) = delete;lock_guard(lock_guard &&) = delete;lock_guard &operator=(const lock_guard &) = delete;lock_guard &operator=(lock_guard &&) = delete;private:Mutex_ *m_mt;
};

其实内存控制也和这个差不多,只要把相关的内存创建和回收控制好即可。
在STL的标准库中,很多实现都应用到了RAII,比如常见的lock_guard,智能指针和stream等,所以还是建议大家把这个技巧弄清楚明白。

五、总结

记得以前总结过RAII相关的资料,可最近回头一看,没有找到 。于是,就只好将其再总结一篇,如果找到,就算重复总结吧。其实RAII更像是一种无奈之举,总得有一种安全的处理资源的方式啊。恰好,在C++中有这种变通的实现方式。其实上面还是有一些细节没有提到,比如创建和释放资源如果出现异常怎么办(即构造函数或析构函数如何处理异常)?这个在相关的知识中有过说明就不再详细阐述了。
或许这就是古人常说的,天无绝人之路!所以,对网上说的什么C++/c要被清退的说法,淡然处之即好。该来的一定会来,该走的也一定会走,不是谁说让谁走谁就会走。

相关文章:

跟我学C++中级篇——RAII

一、什么是RAII Resource Acquisition Is Initialization&#xff0c;资源获取即初始化。C/C的开发者都知道&#xff0c;在这类语言的开发中&#xff0c;内存需要手动来控制。也就是说&#xff0c;释放和回收内存得开发者亲历亲为。从某种角度看&#xff0c;能够把控内存的细节…...

C语言第九周课——经典算法

目录 一、冒泡法排序 1.1原理 1.2代码实现&#xff08;以升序排序为例&#xff09; 1.3逻辑 1.4分析 二、二分法查找 2.1原理 2.2代码实现 2.3逻辑 2.4算法效率分析 三、素数判断 3.1原理 3.2代码实现 3.3逻辑 3.4分析 一、冒泡法排序 1.1原理 冒泡排序&…...

【Pikachu】XML外部实体注入实战

若天下不定&#xff0c;吾往&#xff1b;若世道不平&#xff0c;不回&#xff01; 1.XXE漏洞实战 首先写入一个合法的xml文档 <?xml version "1.0"?> <!DOCTYPE gfzq [<!ENTITY gfzq "gfzq"> ]> <name>&gfzq;</name&…...

vue2项目中在线预览csv文件

简介 希望在项目中&#xff0c;在线预览.csv文件&#xff0c;本以为插件很多&#xff0c;结果都只是支持excel&#xff08;.xls、.xlsx&#xff09;一到.csv就歇菜。。。 关于文件预览 vue-office&#xff1a;文档、 查看在线演示demo&#xff0c;支持docx、.xlsx、pdf、ppt…...

基于VUE实现语音通话:边录边转发送语言消息、 播放pcm 音频

文章目录 引言I 音频协议音频格式:音频协议:II 实现协议创建ws对象初始化边录边转发送语言消息 setupPCM按下通话按钮时开始讲话,松开后停止讲话播放pcm 音频III 第三库recorderplayer调试引言 需求:电台通讯网(电台远程遥控软件-超短波)该系统通过网络、超短波终端等无线…...

PMP--一、二、三模、冲刺--分类--变更--技巧--特点

文章目录 一模二模三模冲刺14.敏捷--不确定性、风险和生命周期选择14.敏捷--特点--敏捷范围灵活&#xff0c;敏捷拥抱变更14.敏捷--阶段关口--在不同的组织、行业或工作类型中&#xff0c;阶段关口可能被称为阶段审查、阶段门、关键决策点和阶段入口或阶段出口。组织可以通过这…...

CSS Grid 布局实战:从入门到精通

文章目录 前言一、CSS Grid 布局概述1.1 什么是 CSS Grid 布局&#xff1f;1.2 主要特点 二、基本概念2.1 网格容器2.2 网格线2.3 网格轨道2.4 网格区域 三、常用属性3.1 定义网格结构3.2 控制网格项的位置3.3 控制网格间距3.4 自动填充和重复 四、实践案例4.1 项目结构4.2 HTM…...

git创建远程仓库,以gitee码云为例GitHub同理

git远程Remote服务端仓库构建的视频教程在这 Git建立服务端Remote远程仓库&#xff0c;gitee码云例&#xff0c;Github_哔哩哔哩_bilibili 1、登gitee码云/Github 登录 - Gitee.com https://github.com/ &#xff08;没账号的注册一下就行&#xff09; 点击如下图位置的创…...

Java爬虫(HttpURLConnection)详解

文章目录 Java爬虫&#xff08;HttpURLConnection&#xff09;详解一、引言二、准备工作1、环境配置2、理解HttpURLConnection 三、发送GET请求1、创建URL对象2、打开连接3、设置请求方法4、连接并读取响应5、处理返回的数据 四、发送POST请求1、设置输出2、发送请求体3、读取响…...

基于STM32的智能停车管理系统设计

引言 随着城市汽车保有量的增加&#xff0c;停车难问题日益严重&#xff0c;传统停车管理方式效率低下&#xff0c;无法满足现代化需求。为了解决这一问题&#xff0c;本项目基于STM32微控制器设计了一种智能停车管理系统。系统能够通过传感器实时监测停车位的使用情况&#x…...

【循环神经网络】

循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类用于处理序列数据的神经网络&#xff0c;擅长处理具有时间依赖或顺序结构的数据。RNN通过循环连接的结构&#xff0c;使得当前时刻的输出可以受之前时刻信息的影响&#xff0c;因此被广泛应用于自然语…...

优选算法 - 4 ( 链表 哈希表 字符串 9000 字详解 )

一&#xff1a;链表 1.1 链表常用技巧和操作总结 1.2 两数相加 题目链接&#xff1a;两数相加 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* …...

CTF-RE 从0到N: windows反调试-获取Process Environment Block(PEB)信息来检测调试

在Windows操作系统中&#xff0c;Process Environment Block (PEB&#xff0c;进程环境块) 是一个包含特定进程信息的数据结构。它可以被用于反调试中 如何获取PEB指针&#xff1f; 在Windows操作系统中&#xff0c;获取PEB指针的常见方法主要有以下几种。&#xff1a; 1. 使…...

STM32开发基础阶段复习

1.使用寄存器方式点亮LED灯的三个步骤是什么&#xff1f; 首先使能RCC_APB2ENR&#xff08;外设时钟使能寄存器&#xff09;对应的GPIO端口时钟,即给LED这个外设使能时钟。 配置对应GPIO端口&#xff0c;配置为通用推挽输出&#xff0c;输出速度可以选择最大。 将GPIO端口输…...

搜维尔科技:SenseGlove触觉反馈手套开箱+场景测试

搜维尔科技&#xff1a;SenseGlove触觉反馈手套开箱场景测试 SenseGlove触觉反馈手套开箱场景测试...

在k8s上部署Crunchy Postgres for Kubernetes

目录 一、前言二、安装Crunchy Postgres for Kubernetes三、部署一个简单的postgres集群四、增加pgbouncer五、数据备份六、备份恢复七、postgres配置参数七、数据导入 一、前言 Crunchy Postgres可以帮助我们在k8s上快速部署一个高可用、具有自动备份和恢复功能的postgres集群…...

大模型(LLMs)进阶篇

大模型&#xff08;LLMs&#xff09;进阶篇 一、什么是生成式大模型&#xff1f; 生成式大模型&#xff08;一般简称大模型LLMs&#xff09;是指能用于创作新内容&#xff0c;例如文本、图片、音频以及视频的一类深度学习模型。相比普通深度学习模型&#xff0c;主要有两点不…...

近几年新笔记本重装系统方法及一些注意事项

新笔记本怎么重装系统&#xff1f; 近几年的新笔记本默认开启了raid on模式或vmd选项&#xff0c;安装过程中会遇到问题&#xff0c;新笔记本电脑重装自带的系统建议采用u盘方式安装&#xff0c;默认新笔记本有bitlocker加密机制&#xff0c;如果采用一键重装系统或硬盘方式安装…...

小程序19-微信小程序的样式和组件介绍

在小程序中不能使用 HTML 标签&#xff0c;也就没有 DOM 和 BOM&#xff0c;CSS 也仅支持部分选择器 小程序提供了 WXML 进行页面结构的编写&#xff0c;WXSS 进行页面的样式编写 WXML 提供了 view、text、image、navigator等标签构建页面结构&#xff0c;小程序中标签称为组件…...

Chrome 浏览器开启打印模式

打开开发者工具ctrl shift p输入print 找到 Emulate CSS print media type...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

spring boot使用HttpServletResponse实现sse后端流式输出消息

1.以前只是看过SSE的相关文章&#xff0c;没有具体实践&#xff0c;这次接入AI大模型使用到了流式输出&#xff0c;涉及到给前端流式返回&#xff0c;所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起&#xff0c;为了跨网段推流&#xff0c;千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...

PCA笔记

✅ 问题本质&#xff1a;为什么让矩阵 TT 的行列式为 1&#xff1f; 这个问题通常出现在我们对数据做**线性变换&#xff08;旋转/缩放&#xff09;**的时候&#xff0c;比如在 PCA 中把数据从原始坐标系变换到主成分方向时。 &#x1f4cc; 回顾一下背景 在 PCA 中&#xff…...