今天看到RAII(Resource Acquisition Is Initialization,即资源获得即初始化)的时候,脑子里竟然想不出它的意思。
其实这个词自己应该是很熟悉了的,在Exceptional C++和More exceptional C++这两本书中都有提到过RAII的概念,
并且Herb Sutter也给出了详尽的解释和应用。不过从今天自己的反应看来,我只是熟悉了RAII这个词而已,而没有将
它的真正意义记在脑子里,所以想在这里再次学习一下。
Resource Acquisition Is Initialization 是面向对象语言中的一个编程惯用语,是出于异常安全的资源管理
(exception-safe resource management) 的目的而被发明形成的一种广泛使用的技术。总的来说,它是为异常安全服
务的。
这里有四种异常安全类别: No exception safety, basic exception safety, Strong exception safety,
No-throw guarantee. (-_-我只记得两种)。No exception safety 和 No-throw guarantee的含义显而易见,这里就不多说了。
Strong exception safety 指实现了 提交和回滚语义 (commit and rollback semantics)的异常安全类别,顾名思义,这种
异常安全类别分为两种情况——commit和rollback。在操作成功的情况下,操作表现为commit状态,即操作成功,所有
数据都被更新;若操作失败,则该种异常安全类别下该操作会表现为rollback状态,所有数据都会“rollback”,与操作前
的数据状态保持一致,不会产生side-effects。
Basic exception safety 级别的异常安全允许有side-effects,但保证没有资源泄露。
for instance, 看如下代码:
{
.
.
Color* pColor = new Color;
.
.
if (error) throw std::logic_error ();
.
.
delete pColor;
}
如果函数的中间部分,因error而抛出异常,则函数底部的delete语句永远不会得到执行的机会,函数因此会造成resource-leak。
就这段代码来说,它不是异常安全的,它是No exception safety的。
但如果我们在编写代码时有意的注重异常安全,并运用RAII技术,则可以容易地做到代码异常安全。如下:
template
class Holder
{
public:
expicit Holder (T * ptr)
: ptr_ (ptr) {}
~Holder () { delete ptr_; }
private:
Holder (Holder& other);
Holder operator = (Holder& other);
T* ptr_;
};
{
.
.
Holder holderColor (new Color);
.
.
if (error) throw std::logic_error ();
.
.
//no delete statement
}
在上面的代码中,我们定义了一个Holder类以管理Color的资源指针。在这片代码中,即使函数中间有异常抛出,Color资源
也能够正常被Holder类的西沟函数释放,因为C++标准保证,函数因抛出异常儿离开scope时,所有所在范围的类变量的析构函
数都将被正确调用(-_-大概是这个意思)。所以当控制因异常抛出儿离开函数时,Holder变量holderColor的析构函数将被调用,保
证资源被释放。Holder类在构造时(即初始化)获得资源,析构时释放获得的资源,想必这就是资源获得即初始化的意思(-_-我猜想)
。
RAII的作用有很多:
1. 消除(一定程度上)指针。在C/C++中,很多资源泄露是有指针引起的。
2. 使程序员从delete语句中解脱出来。为了保证资源泄露的发声,函数中可能会有多个返回点、异常抛出点出现delete
语句,那样重复的delete会让人很厌烦。
3. 降低代码的可读性与可维护性。理由同第二条。
等等(-_-)
以上都为个人理解,不到之处敬请理解,欢迎评论。