WEB开发网
开发学院软件开发C语言 RAII 阅读

RAII

 2009-06-08 08:32:23 来源:WEB开发网   
核心提示: 显而易见,对于资源是否有效的判断已经使得程序员是否疲惫,RAII(5),而且,他们还需要不停的维护资源的指针,这里就不做任何阐述了,3. 使用 RAII 时,只要任何一步出错,程序都将变得脆弱

显而易见,对于资源是否有效的判断已经使得程序员是否疲惫,而且,他们还需要不停的维护资源的指针,只要任何一步出错,程序都将变得脆弱,更作用的是,不但编写这样的程序不会有任何快感,使用这样的代码也十分郁闷,比如调用 GetChar 的时候,需要当心函数抛出的来异常,不断的写 try catch(如果使用 error codes 来表示错误,也需要不断的判断函数执行是否出错),在一些复杂的情况下,更加让人抓狂:

bool AddGroup(int idUser)
{
    // 检查 idUser 是否允许加入组
    // ...
    // 检查成功,允许加入,扣去入会费
    SpendUserMoney(idUser, 10000);
    // 对于入会成功用户增加一个等级
    AddUserLevel(idUser);
    // 等等操作
    // 将其写入文件中
    try
    {
        // 在文件中写入用户当前等级,入会花费等信息
        file.Write("xxx");
    } catch (const Open_first&)
    {
        // 异常出现
        // 恢复现场
        AwardUserMoney(10000);
        ReduceUserLevel(idUser);
        // 等等
    }
}

由上例可见,为了处理异常情况而做的工作太大,而且我们每次调用时都要进行相似的处理。虽然上例不一定完全合乎实际情况,或许你认为它还有改良的空间,不过无论如何,我们难免要做太多多余的工作。

自此,已经谈完了 RAII 设计方式的好处,那么下面谈谈应该注意一些什么:

1. 如果没有必要,应该禁止复制。

如果没有必要应该禁用复制构造函数和赋值操作符,这点很重要,如果没有按需要定义复制构造函数和赋值操作符,那么得到的结果通常是:非内存资源被创建一次,释放多次。

2. 如果需要复制,应该谨慎考虑。

重新定义复制构造函数和赋值操作符是必须的。怎么写它们是一个问题,具体的方案依赖于实际的需要,可以使用深拷贝,也可以使用类似于 shared_ptr 的引用计数机制,或者传递所有权。

总结一下:

1. 使用 RAII 能够将非内存资源的生命周期管理转为内存资源生命周期的管理,使得我们能够使用管理内存资源的手段来管理非内存资源,例如 auto_ptr,shared_ptr。

2. 维护 invariant 能够简化编程,使的代码简洁优雅。RAII 设计方式维护了这么一条 invariant:对象存在则资源有效。除此之外,我们还可以使用异常机制来维护另外一条 invariant:函数要么执行成功得到正确的结果,要么抛出异常。对此条,这里就不做任何阐述了。

3. 使用 RAII 时,应该警惕复制行为。

上一页  1 2 3 4 5 

Tags:RAII

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接