1.什么是RAII?

RAII(Resource Acquisition Is Initialization)机制是Bjarne Stroustrup首先提出的,也称直译为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的机制。
C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。
RAII 机制就是利用了C++的上述特性,在需要获取使用资源RES的时候,构造一个临时对象(T),在其构造T时获取资源,在T生命期控制对RES的访问使之始终保持有效,最后在T析构的时候释放资源。以达到安全管理资源对象,避免资源泄漏的目的。

2.为什么要使用RAII?

那么我们经常所说的资源是如何定义的?说到资源,我们立刻能想到的就是内存啊,文件句柄等等啊,但只有这些吗?
对于资源的概念不要想象的太狭隘,在计算机系统中,资源是个定义宽泛的概念,所有数量有限且对系统正常运行具有一定作用的元素都是资源。比如:网络套接字、互斥锁、文件句柄、内存、数据库记录等等,它们属于系统资源。由于系统的资源是有限的,就好比自然界的石油,铁矿一样,不是取之不尽,用之不竭的。
所以,我们在编程使用系统资源时,都必须遵循一个步骤:

1.申请资源;
2.使用资源;
3.释放资源。

第一步和第三步缺一不可,因为资源必须要申请才能使用的,使用完成以后,必须要释放,如果不释放的话,就会造成资源泄漏。

3.实战应用

3.1一个简单的例子:指针申请空间,释放空间

void Func()
{  int *ip = new int[10];  //operations  //operations //operations  delete[] ip;//if not free mem, memory overflow
}

使用RAII技术后:

template<class PointerType>
class My_Pointer
{
public:  My_Pointer(PointerType* _ptr, size_t sz)  {  _ptr = new PointerType[sz];  m_ptr = _ptr;  }  ~My_Pointer()  {  delete []m_ptr;  }
protected:  PointerType    m_ptr;
}  

3.2 scope lock (局部锁技术)
在很多时候,为了实现多线程之间的数据同步,我们会使用到 mutex,critical section,event,singal 等技术。但在使用过程中,由于各种原因,有时候,我们会遇到一个问题:由于忘记释放(Unlock)锁,产生死锁现象。
采用RAII 就可以很好的解决这个问题,使用着不必担心释放锁的问题. 示例代码如下:
My_scope_lock 为实现 局部锁的模板类.
LockType 抽象代表具体的锁类 .如基于 mutex 实现 mutex_lock 类

template<class LockType>
class My_scope_lock
{
public:  My_scope_lock(LockType& _lock):m_lock(_lock)  {   m_lock.occupy();  }  ~My_scope_lock()  {  m_lock.relase();  }
protected:  LockType    m_lock;
}  

使用的时候:

//global vars
int counter = 0;
void routine();
mutex_lock  m_mutex_lock;
void routine()
{  My_scope_lock l_lock(m_mutex_lock);  counter++;  //others...
}  

我们可以根据上面的例子类推出好多这样例子。如读写文件的时候很容易忘记关闭文件,如果借用 RAII技术,就可以规避这种错误。再如对数据库的访问,忘记断开数据库连接等等都可以借助RAII 技术也解决。

4.RAII模板化实现

按照上节的做法,如果你有很多个资源对象要用RAII方式管理,按这个办法就要为每个类写一个RAII类。
想到这里,我瞬间觉得好烦燥,都是类似的代码,却要一遍一遍的重复,就不能有个通用的方法让我少写点代码嘛!!!
于是我利用C++11的新特性(类型推导、右值引用、移动语义、类型萃取、function/bind、lambda表达式等等)写了一个通用化的RAII机制,满足各种类型资源的管理需求。

//
// RAII.h
//
// Library: Foundation
// Package: Core
// Module:  RAII
//
// Definition of the RAII template class and friends.
//
//#include "Wishbone/Foundation.h"
#include <type_traits>
#include <functional>namespace Wishbone
{/* 元模板,如果是const类型则去除const修饰符 */template<typename T>struct no_const{using type = typename std::conditional<std::is_const<T>::value, typename std::remove_const<T>::type, T>::type;};///  RAII方式管理申请和释放资源的类/// 对象创建时,执行acquire(申请资源)动作(可以为空函数[]{})/// 对象析构时,执行release(释放资源)动作/// 禁止对象拷贝和赋值class RAII{public:typedef std::function<void()> FunctionType;/// release: 析构时执行的函数/// acquire: 构造函数执行的函数/// default_com:_commit,默认值,可以通过commit()函数重新设置explicit RAII(FunctionType release, FunctionType acquire = [] {}, bool default_com = true) noexcept :_commit(default_com),_release(release){acquire();}/// 对象析构时根据_commit标志执行_release函数~RAII() noexcept{if (_commit)_release();}/// 移动构造函数 允许右值赋值RAII(RAII&& rv) noexcept : _commit(rv._commit),_release(rv._release){rv._commit = false;};///RAII& commit(bool c = true) noexcept;protected:std::function<void()> _release;private:RAII(const RAII&);RAII& operator=(const RAII&) = delete;bool _commit;}; /* RAII *//// inlinsinline RAII& RAII::commit(bool c = true) noexcept{ _commit = c; return *this; };/// 用于实体资源的RAII管理类/// T为资源类型/// acquire为申请资源动作,返回资源T/// release为释放资源动作,释放资源Ttemplate<typename T>class RAIIVar{public:typedef std::function<T()> AcquireType;typedef std::function<void(T &)> ReleaseType;///explicit RAIIVar(AcquireType acquire, ReleaseType release) noexcept :_resource(acquire()),_release(release){}/// 移动构造函数RAIIVar(RAIIVar&& rv) :_resource(std::move(rv._resource)),_release(std::move(rv._release)){rv._commit = false;//控制右值对象析构时不再执行_release}/// 对象析构时根据_commit标志执行_release函数~RAIIVar() noexcept{if (_commit)_release(_resource);}RAIIVar<T>& commit(bool c = true) noexcept{ _commit = c; return *this;};T& get() noexcept{return _resource; }T& operator*() noexcept{return get();}template<typename _T = T>typename std::enable_if<std::is_pointer<_T>::value, _T>::type operator->() const noexcept{return _resource;}template<typename _T = T>typename std::enable_if<std::is_class<_T>::value, _T*>::type operator->() const noexcept{return std::addressof(_resource);}private:bool        _commit = true;T           _resource;ReleaseType _release;};/// 创建 RAII 对象,/// 用std::bind将M_REL,M_ACQ封装成std::function<void()>创建RAII对象/// RES      资源类型/// M_REL    释放资源的成员函数地址/// M_ACQ    申请资源的成员函数地址template<typename RES, typename M_REL, typename M_ACQ>RAII make_raii(RES & res, M_REL rel, M_ACQ acq, bool default_com = true) noexcept{static_assert(std::is_class<RES>::value, "RES is not a class or struct type.");static_assert(std::is_member_function_pointer<M_REL>::value, "M_REL is not a member function.");static_assert(std::is_member_function_pointer<M_ACQ>::value, "M_ACQ is not a member function.");assert(nullptr != rel && nullptr != acq);auto p_res = std::addressof(const_cast<typename no_const<RES>::type&>(res));return RAII(std::bind(rel, p_res), std::bind(acq, p_res), default_com);}template<typename RES, typename M_REL>RAII make_raii(RES & res, M_REL rel, bool default_com = true) noexcept{static_assert(std::is_class<RES>::value, "RES is not a class or struct type.");static_assert(std::is_member_function_pointer<M_REL>::value, "M_REL is not a member function.");assert(nullptr != rel);auto p_res = std::addressof(const_cast<typename no_const<RES>::type&>(res));return RAII(std::bind(rel, p_res), [] {}, default_com);}} // namespace Wishbone

C++之RAII机制相关推荐

  1. C++中的RAII机制

    什么是RAII? RAII是Resource Acquisition Is Initialization(wiki上面翻译成 "资源获取就是初始化")的简称,是C++语言的一种管理 ...

  2. 【C++设计技巧】C++中的RAII机制

    随笔- 427  文章- 0  评论- 4 作者:gnuhpc  出处:http://www.cnblogs.com/gnuhpc/ 1.概念 Resource Acquisition Is Init ...

  3. C 多线程的互斥锁应用RAII机制

    什么是RAII机制 RAII是Resource Acquisition Is Initialization(翻译成 "资源获取即初始化")的简称,是C 语言的一种管理资源.避免资源 ...

  4. C++RAII机制(智能指针原理)

    原文详细整理 C++中的RAII机制 - 码到城攻RAII机制,是C++语言的一种管理资源.避免泄漏的惯用法https://www.codecomeon.com/posts/200/ 何为RAII R ...

  5. C++程序设计机制:RAII机制

    1.背景 C/C++程序开发中,管理堆上分配的内存容易出错,常见的就是内存泄漏.原则上,只要我们足够仔细,在每一次动态分配内存之后,使用完毕后,手动delete即可释放掉内存,可是这必然会加大我们的工 ...

  6. RAII机制原理分析

    本文转载自: https://blog.csdn.net/wozhengtao/article/details/52187484 前言 RAII的基本思想就是当对象的生命周期结束时,自动调用起析构函数 ...

  7. C++ RAII机制

    最近一直在碰到这个RAII机制,但是似乎没搞清楚这啥意思.现在大概明白了,C++的RAII机制就是类似于C#或者Java的GC机制,垃圾回收.合理的回收系统资源,避免程序员大量的写重复的delete代 ...

  8. C++——RAII机制

    文章目录 我们知道,资源的使用一般经历三个步骤 a.获取资源 b.使用资源 c.销毁资源 资源的销毁往往是程序员经常忘记的一个环节,忘记销毁资源可能会造成内存泄露,怎么解决呢?--RAII RAII: ...

  9. C++高阶 RAII机制(以对象管理资源)

    文章目录 1.什么是RAII 2.RAII的原理 3.实例: 1.什么是RAII RAII(Resource Acquisition Is Initialization)是由c++之父Bjarne S ...

最新文章

  1. dubbo-provider-deploy
  2. 使用org.apache.commons.io.FileUtils,IOUtils工具类操作文件
  3. 上传文件Base64格式(React)
  4. 【bzoj 2434】【codevs 1946】[Noi2011]阿狸的打字机(AC自动机)
  5. php.ini 302,302使用nginx和WordPress重定向循环
  6. 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义
  7. dyve/django-bootstrap-toolkit
  8. VS2011最新版本 新功能 新增特性 简介Visual Studio 2011
  9. 创建ORACLE定时任务 任务日志记录
  10. 信息系统项目管理师考试论文写作复习笔记(4)-范围管理论文2
  11. 网易公开课APP如何修改视频缓存地址
  12. 如何搭建WordPress个人博客网站?
  13. java 杨辉三角_Java语言杨辉三角
  14. Android 读取外接储存设备的数据(如挂载的U盘,SD卡等)
  15. 恶意程序利用Linksys路由器漏洞在路由器中传播
  16. 全网最新PHP教程大全,PHP进阶自学教程大全!
  17. d3.js 刷新折线图(包括坐标轴及路径的刷新及信息点提示)
  18. 计算机专业英语中tour的意思,计算机专业英语自我介绍
  19. 解决git错误: error: The following untracked working tree files would be overwritten by merge
  20. [JVM]了断局:内存模型与线程

热门文章

  1. wordpress安装及使用
  2. 关于dword ptr 指令的意思
  3. java让服务器停止运行,java调用远程服务器的shell脚本以及停止的方法实现
  4. ibm mq并发访问队列_消息队列之九问九答
  5. 慕课堂计算机word,数字技能 – 办公工具(Microsoft Word、Excel、Power Point)
  6. 403禁止访问:访问被拒绝如何解决_死链接对网站有哪些危害?如何处理死链接?...
  7. Non-zero CodeForces - 1300A
  8. HTML5的入门教程
  9. mysql中合并函数_MYSQL分组合并函数
  10. rabbitmq使用_RabbitMQ的使用(二) RabbitMQ服务在单机中做集群