RAII机制和智能指针

2024-03-27 21:08
文章标签 指针 智能 机制 raii

本文主要是介绍RAII机制和智能指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 RAII介绍

RAII全称是Resource Acquisition Is Initialization,翻译过来是资源获取即初始化,RAII机制用于管理资源的申请和释放。对于资源,我们通常经历三个过程,申请,使用,释放,这里的资源不仅仅是内存,也可以是文件、socket、锁等等。但是我们往往只关注资源的申请和使用,而忘了释放,这不仅会导致内存泄漏,可能还会导致业务逻辑的错误,RAII就用来解决此类问题。

2 C++中的RAII使用

我们看以下例子。

std::mutex m;
void fn() 
{m.lock();                 使用资源m.unlock();                
}

上面的代码是对互斥变量的使用,我们看到加锁和解锁是成对出现的。如果我们忘了unlock那么别的线程再也无法枷锁成功,而且还会导致一直阻塞。我们看C++怎么解决这个问题。

std::mutex m;
void fn()
{std::lock_guard<std::mutex> guard(m); do_something();                            // 指向完函数后,guard会被析构,从而mutex也会被释放
}      

我们看到上面的代码中,我们只需要加锁,操作资源,不需要手动解锁。那么RAII是怎么做的呢?我们看看lock_guard的实现。

template <class Mutex> 
class lock_guard {private:Mutex& mutex_;public:lock_guard(Mutex& mutex) : mutex_(mutex) { mutex_.lock(); }~lock_guard() { mutex_.unlock(); }// 禁止复制和赋值lock_guard(lock_guard const&) = delete;lock_guard& operator=(lock_guard const&) = delete;};

我们看到实现很简单,在创建一个lock_guard对象的时候,lock_guard会初始化内部字段,并且执行加锁操作。当lock_guard析构的时候,会指向解锁操作,所以借助这个类,我们就不需要关注解锁的操作了,具体的原理是利用了C++对象离开作用域后会自定执行析构函数。

3 RAII实践

3.1 文件管理

理解了使用和原理后,我们也可以利用RAII机制编写自己的类。

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
class FD {private:int fd;public:FD(const char *s) { fd = open(s, O_RDONLY); printf("构造函数:打开文件的文件描述符:%d\n", fd);}~FD() { int ret = close(fd); printf("析构函数:关闭文件执行结果:%d\n", ret);}// 重载*运算符int operator *() {return fd;}FD(FD const&) = delete;FD& operator=(FD const&) = delete;
};int main()
{const char* filePath = "/dev/null";FD fd(filePath);// 操作资源printf("文件描述符:%d\n", *fd);return 0;// 离开作用域,自动析构,关闭fd
}

我们封装了一个文件管理类,这样我们就可以只关注打开资源,操作资源而不需要手动关闭资源了。

3.2 智能指针

我们再看一下RAII的使用场景,就是智能指针的实现。

#include<iostream>
#include<stdio.h>
using namespace std;template<class T>
class SmartPoint
{T* point;
public:SmartPoint(T *ptr = nullptr) :point(ptr) {}~SmartPoint() {if (point) {// 会调用point指向对象的的析构函数delete point;}}// 使用智能指针就像使用内部包裹的的对象一样T& operator*() { return *point; }T* operator->() { return point; }
};class Demo {public:Demo() {printf("执行构造函数\n");}~Demo() {printf("执行析构函数\n");}void show() {printf("hello\n");}
};int main() {SmartPoint<Demo> smartPoint(new Demo());smartPoint->show();Demo &demo = *smartPoint;demo.show();
}

执行上面代码输出

执行构造函数
hello
hello
执行析构函数

我们看到SmartPoint的实现中,在初始化SmartPoint的时候会传入被管理的对象,并通过重载*和->运算符实现对包裹对象的使用,最后在SmartPoint被析构的时候,也会把包裹对象的内存给析构掉。

4 RAII在Rust的应用

RAII机制和智能指针不仅在C++中使用,在新语言Rust中,同样用到了该技术。

struct Demo(u32);
// 实现Drop trait跟踪Demo的行为
impl Drop for Demo {fn drop(&mut self) {println!("执行析构");}
}
fn main() {// 分配堆内存let demo_box = Box::new(Demo(1));// 操作资源println!("{}", demo_box.0);// 自动析构
}

执行上面代码输出

1
执行析构

Box就是Rust中的智能指针,使用的方式和C++中类似,初始化Box时传入一个对象,然后交给Box管理,使用demo_box就像是要Demo结构体一样。最后在函数执行完时包裹对象的内存会被释放。

这篇关于RAII机制和智能指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853390

相关文章

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

C# async await 异步编程实现机制详解

《C#asyncawait异步编程实现机制详解》async/await是C#5.0引入的语法糖,它基于**状态机(StateMachine)**模式实现,将异步方法转换为编译器生成的状态机类,本... 目录一、async/await 异步编程实现机制1.1 核心概念1.2 编译器转换过程1.3 关键组件解析

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

Java中的xxl-job调度器线程池工作机制

《Java中的xxl-job调度器线程池工作机制》xxl-job通过快慢线程池分离短时与长时任务,动态降级超时任务至慢池,结合异步触发和资源隔离机制,提升高频调度的性能与稳定性,支撑高并发场景下的可靠... 目录⚙️ 一、调度器线程池的核心设计 二、线程池的工作流程 三、线程池配置参数与优化 四、总结:线程