RAII技术被认为是C++中管理资源的最佳方法,进一步引申,使用RAII技术也可以实现安全、简洁的状态管理,编写出优雅的异常安全的代码。
资源管理
RAII是C++的发明者Bjarne Stroustrup提出的概念,RAII全称是“Resource Acquisition is Initialization”,直译过来是“资源获取即初始化”,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,应该使用类来管理资源,将资源和对象的生命周期绑定。
智能指针(std::shared_ptr
和std::unique_ptr
)即RAII最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏。在线程同步中也有RAII机制的身影,使用std::unique_lock
或std::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_;
}