前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我攻克的技术见解:RAII惯用法(c++)

我攻克的技术见解:RAII惯用法(c++)

原创
作者头像
ys.h
发布2024-01-14 23:27:04
2982
发布2024-01-14 23:27:04
举报
文章被收录于专栏:c++设计模式

1.RAII惯用法介绍

RAII是Resource Acquisition Is Initialization的缩写,即 “资源获取即初始化”。

RAII 是C++语言的一种管理资源、避免泄漏的惯用法。简单点来说,就是在构造对象的时候获取资源,在使用的时候调用资源,最后析构的时候销毁资源来达到资源的管理和避免泄露。

那么问题来了,资源又是什么呢?

谈到资源,大家第一时间想到的应该是内存,即还有多少内存空间可用,实际上从广义角度讲,资源还可以指很多东西,比如网络连接(connect),句柄(socket),事件(event),线程(thread)等等。这些都可以当作资源,之前跟一个大佬学习也是这样做的,于是我才发现这是一种惯用的思维,大家按照这种写法可以做到使资源安全的释放掉。

2.RAII惯用法详解

在介绍中我们讲了RAII惯用法的三大步骤,获取资源 , 使用资源 , 销毁资源,那么我们的代码也要紧跟着这三步走。

一般情况下我们在局部中使用资源时在退出时我们需要销毁在局部中获取的资源,列如:

先获取一个资源,然后对资源进行操作,操作完了以后再销毁

代码语言:c++
复制
void solve() {
    File* file = fopen(fn , "r")

    do1(file);//操作一

    do2(file);//操作二

    fclose(file);
}

但是我们会遇到一些问题在操作中我们可能遇到异常,需要结束solve() , 这需要在每一次异常时将在局部中获取的资源释放,非常的容易遗忘和维护,这样做会让代码看起来很臃肿,并且使代码效率下降很多,维护的时间也会大大增加。

列如

代码语言:c++
复制
void solve() {
    File* file = fopen(fn , "r")

    try{
        if(!do1(file))
            fclose(file);//操作一
        if(!do2(file))
            fclose(file);
    }
    catch(....)
    {
        fclose(f);                   // 释放资源
        throw;  
    }
    fclose(file);
}

RAII惯用法可以很大程度的弥补这些写法的不足

在里面我们将File抽象成一个类FileEvent,将一个局部对象来表示这个File资源,在系统判断局部对象生命周期结束的时候就会自动调用FileEvent的析构函数来把这个资源自动删除。

如若使用文件file的代码中有异常抛出,难道析构函数还会被调用吗?此时RAII还能如此奏效吗?

问得好。事实上,当一个异常抛出之后,系统沿着函数调用栈,向上寻找catch子句的过程,称为栈辗转开解(stack unwinding)。

代码语言:c++
复制
class FileEvent {
public:
    FileEvent(char const* fn, char const* ch) { p = fopen(fn, ch);//获取资源 }
    ~FileEvent() { fclose(p); //释放资源}
private:
    FILE *p;
};

void Solve()
{
    FileEvent file1("n1.txt", "r"); 
    Do();       //若抛出异常,一样会调用析构
    FileHandle file2("n2.txt", "rw")
}

当到Do()时,file1对象已经创建成功了,file2还未创建,如果Do() 中抛出了异常的话,file1的构造函数就会调用(析构函数的调用顺序和构造函数的调用顺序相反 , 假设先构造顺序为f1,f2,那么析构顺序则为f2,f1)。

3.总结

RAII实际上是一种设计模式,该设计模式的使用位置应该是对于资源对象的管理,这样写的出的代码不仅优雅并且简洁,而且还做到了异常安全。

非常的好用~。

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.RAII惯用法介绍
    • 那么问题来了,资源又是什么呢?
    • 2.RAII惯用法详解
      • 一般情况下我们在局部中使用资源时在退出时我们需要销毁在局部中获取的资源,列如:
      • 3.总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档