前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊RAII

聊聊RAII

作者头像
雪月清
发布2023-10-25 17:14:00
1600
发布2023-10-25 17:14:00
举报
文章被收录于专栏:雪月清的随笔

原理

RAII(Resource Acquisition Is Initialization),全称资源获取即初始化,1984-1989年期间,比雅尼·斯特劳斯特鲁普和安德鲁·柯尼希在设计C++异常时,为解决资源管理时的异常安全性而使用了该用法,后来比雅尼·斯特劳斯特鲁普将其称为RAII

RAII要求,资源的有效期与持有资源的对象的生命期严格绑定,即由对象的构造函数完成资源的分配(获取),同时由析构函数完成资源的释放。在这种要求下,只要对象能正确地析构,就不会出现资源泄漏问题

我们来看看cppreference上提供的对比案例

未使用RAII的情况

使用RAII的情况

lock_guard的实现如下图所示,在构造函数完成加锁,析构函数中释放锁,并且禁用了拷贝构造函数和赋值运算

由于RAII可以极大地简化资源管理,并有效地保证程序的正确和代码的简洁,所以通常会强烈建议在C++工程中使用它

RAII在Android底层源码的应用更是随处可见,比如SkImageDecoder_libpng中

应用

这里我们来看看FFmpeg Demo开源工程中RAII的应用

在将java层String对象通过JNI传递时,我们通常都会写如下代码

代码语言:javascript
复制
// jPath type is jstring
const char *path = env->GetStringUTFChars(jPath, nullptr);

// ....

if (path != nullptr) {
    env->ReleaseStringUTFChars(jPath, path);
}

样板代码写起来繁琐,而且一旦忘记调用相关release接口就会导致内存泄露

在Android源码的libnativehelper下提供了一个基于RAII思想的工具类

ScopedUtfChars的使用方式如下

代码语言:javascript
复制
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_xyq_libffplayer_FFPlayer_nativePrepare(JNIEnv *env, jobject thiz, jlong handle,
                                                      jstring path, jobject surface) {
    ATRACE_CALL();
    auto *player = reinterpret_cast<FFMpegPlayer *>(handle);
    ScopedUtfChars scopedPath(env, path);
    std::string s_path = scopedPath.c_str();
    bool result = false;
    if (player) {
        result = player->prepare(env,s_path, surface);
    }
    return result;
}

ScopedUtfChars的实现如下

除了jstring外,在JNI开发中我们经常使用的jXXArray也有类似问题,同样可以使用RAII进行优化

完整代码可以点击文末的"阅读原文"获取

~~END~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 雪月清的随笔 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档