RAII

在学习 C++ 的时候经常见到“资源获取即初始化”这句话。一直困惑这句话要表达的意思,是强调“资源获取”还是强调“初始化”,字面意思:获得系统资源这个行为就是“初始化”。不理解到底是指什么。

维基百科怎么说?

我们看 RAII-Wikipedia 中的叙述:

RAII全称为Resource Acquisition Is Initialization,它是在一些面向对象语言中的一种惯用法。XX 在设计C++异常时,为解决资源管理时的异常安全性而使用了该用法。

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

结合维基百科中给的例子,知道了是怎样的使用形式:将资源抽象为类,用对象代表资源,把管理资源的任务转化为管理对象的任务,将资源的获取和释放与对象的构造和析构对应起来,从而确保在对象的生存期内资源始终有效,对象销毁时资源必被释放。——而这是之前就接触过得。虽然不知道 RAII,但它一直就在我们编写代码的过程中。

什么是资源?

参考 C++中的RAII机制

在计算机系统中,资源是数量有限且对系统正常运行具有一定作用的元素。比如:网络套接字、互斥锁、文件句柄和内存等等,它们属于系统资源。由于系统的资源是有限的,所以,我们在编程使用系统资源时,都必须遵循一个步骤:

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

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

多数情况下,资源是不具备拷贝语义的,所以,RAII临时对象一般也不允许复制和赋值。网上能够看到的示例代码,包括 C++中的RAII机制,大都是将拷贝构造函数、拷贝赋值运算符设置为 private 私有,但在 C++11 新标准中是存在 delete 关键字,可以将此函数设置为 delete 的。

RAII机制是进行资源管理的有力武器,C++程序员依靠RAII写出的代码不仅简洁优雅,而且做到了异常安全。

new 怎么办?

RAII(资源获取即初始化)详解,这篇介绍中提到:(注意,此篇文章中好多代码示例细节不到位,有错误。而且并没有使用新标准。)

一般情况下,RAII临时对象不允许复制和赋值,当然更不允许在heap上创建

给出的示例中也将 new 操作符设置为 private 私有的。道理是通的,因为 RAII 惯用法就是利用“程序段(栈帧)中放置的对象的析构函数”,如果放在堆上,对象变成持久存在的,不能自动销毁……这样岂不是就又绕回到问题的原点了吗