RAII机制介绍
RAII(Resource Acquisition Is Initialization)是由c++之父Bjarne Stroustrup提出的,中文翻译为资源获取即初始化,他说:使用局部对象来管理资源的技术称为资源获取即初始化;这里的资源主要是指操作系统中有限的东西如内存、网络套接字等等,局部对象是指存储在栈的对象,它的生命周期由编译器管理,无需人工介入。
RAII是C++语法体系中的一种合理管理资源避免出现内存泄漏的常用方法。以对象管理资源,利用的就是C++构造的对象最终会被对象的析构函数销毁的原则。
RAII原理
资源的使用一般经历三个步骤:
- 获取资源
- 使用资源
- 销毁资源
RAII的做法是使用一个对象,在其构造时获取对应的资源,在对象生命期内控制对资源的访问,使之始终保持有效,最后在对象析构的时候,释放构造时获取的资源。当定义的局部变量的生命结束时,它的析构函数就会自动的被调用,如此,就不用程序员显示的去调用释放资源的操作了。
使用RAII机制的原因
资源的销毁往往是程序员经常忘记的一个环节,RAII可以让资源自动销毁,避免出现内存泄漏。
RAII机制的优点
- 自动释放资源
- 对象所需的资源只在其生命期内始终保持有效
手动销毁资源的例子:
#include <iostream>
using namespace std;
int main(){
int *p = new int [5];
delete [] p;
p = nullptr;
system("pause");
return 0;
}
上述的的申请、使用、释放资源的程序较为简单,当程序很复杂时,需要把所有new分配的内存delete掉,导致代码臃肿,降低程序的可理解性和可维护性。当操作增多时,处理资源释放的代码就会越来越多,越来越乱。
如果某一个操作发生了异常而导致释放资源的语句没有被调用,怎么办?这个时候,RAII机制就可以派上用场了。
自动销毁资源的例子:
#include <iostream>
using namespace std;
class person {
public:
person(const std::string name = "", int age = 0) :
name_(name), age_(age) {
std::cout << "Init a person!" << std::endl;
}
~person() {
std::cout << "Destory a person!" << std::endl;
}
const std::string& getname() const {
return this->name_;
}
int getage() const {
return this->age_;
}
private:
const std::string name_;
int age_;
};
int main() {
person p;
return 0;
}
当我们在main函数中声明一个局部对象的时候,会自动调用构造函数进行对象的初始化,当整个main函数执行完成后,自动调用析构函数来销毁对象。
RAII步骤总结
- 设计一个类封装资源
- 在构造函数中初始化
- 在析构函数中执行销毁操作
- 使用时声明一个该类的对象
RAII的应用
- 封装多线程的互斥锁
- 管理资源
- 利用RAII过程等待线程完结
- 等等