C++RAII

62 阅读3分钟

RAII技术被认为是C++中管理资源的最佳方法,进一步引申,使用RAII技术也可以实现安全、简洁的状态管理,编写出优雅的异常安全的代码。

资源管理

RAII是C++的发明者Bjarne Stroustrup提出的概念,RAII全称是“Resource Acquisition is Initialization”,直译过来是“资源获取即初始化”,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,应该使用类来管理资源,将资源和对象的生命周期绑定

智能指针(std::shared_ptrstd::unique_ptr)即RAII最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏在线程同步中也有RAII机制的身影,使用std::unique_lockstd::lock_guard对互斥量std:: mutex进行状态管理,在创建时加锁,在销毁时自动解锁

内存只是资源的一种,更加广义的资源管理,如说文件的打开与关闭、windows中句柄的获取与释放等等。简单而言RAII就是指资源在拿到时就已经初始化,一旦不再需要该资源就可以自动释放该资源**,在C++中体现为将资源或状态的获取与对象的生命周期绑定,实现资源的安全管理**。即把管理资源的任务转化为管理对象的任务,将资源的获取和释放与对象的构造和析构对应起来,从而确保在对象的生存期内资源始终有效,对象销毁时资源一定会被释放

对于C++来说,资源在构造函数中初始化(可以再构造函数中调用单独的初始化函数),在析构函数中释放或清理。常见的情形就是在函数调用中创建C++对象时分配资源,在C++对象出了作用域时将其自动清理和释放(不管这个对象是如何出作用域的,不管是否因为某个中间步骤不满足条件而导致提前返回,也不管是否正常走完全部流程后返回)。

#include <iostream> 
using namespace std; 
 
class ArrayOperation { 
public : 
    ArrayOperation() { 
        m_Array = new int [10]; // 初始化时创建资源
    } 
 
    void InitArray() { 
        for (int i = 0; i < 10; ++i) { 
            *(m_Array + i) = i; 
        } 
    } 
 
    void ShowArray() { 
        for (int i = 0; i <10; ++i) { 
            cout<<m_Array[i]<<endl; 
        } 
    } 
 
    ~ArrayOperation() { 
        cout<< "~ArrayOperation is called" <<endl; 
        if (m_Array != NULL ) {  // 销毁时释放资源
            delete[] m_Array;
            m_Array = NULL ; 
        } 
    } 
 
private : 
    int *m_Array; 
}; 
 
bool OperationA(); 
bool OperationB(); 
 
int main() 
{ 
    ArrayOperation arrayOp; 
    arrayOp.InitArray(); 
    arrayOp.ShowArray(); 
    return 0;
}

通常情况下处理资源的类要禁制拷贝或赋值,保证资源管理的准确性:

Class Resource {……};
Class ResourceHandle {
Public:
    Explicit Resourcehandle (Resource *aResource ):r_( aResource ) //获取资源
    ~ResourceHandle() {delete r_;} //释放资源
    Resource *get()    {return r_ ;} //访问资源
Private:
    ResourceHandle (const ResourceHandle &);
    ResourceHandle & operator = (const ResourceHandle &);
    Resource *r_;
}