您的位置:程序门 -> c/c++ -> c++ 语言



raii与异常处理的关系


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


raii与异常处理的关系[已结贴,结贴人:kevinleicn]
发表于:2007-04-27 11:10:30 楼主
raii类的构造函数中在申请资源失败的时候,通常会抛出异常,那么如果在一个不支持异常的c++框架中,能用raii吗?如果能用的话,又是怎么实现的呢?

还请达人们指导.
发表于:2007-04-27 11:13:061楼 得分:0
什么框架不支持c++异常?
发表于:2007-04-27 11:16:132楼 得分:0
比如一些嵌入式环境的c++编译器就不支持异常.
发表于:2007-04-27 11:18:433楼 得分:0
raii是资源获取就是初始化的缩语(resource   acquisition   is   initialization),是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。  

raii   的一般做法是这样的:在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:  
*我们不需要显式地释放资源。  
*采用这种方式,对象所需的资源在其生命期内始终保持有效   ——   我们可以说,此时这个类维护了一个   invariant。这样,通过该类对象使用资源时,就不必检查资源有效性的问题,可以简化逻辑、提高效率。  
发表于:2007-04-27 11:19:144楼 得分:0
那样的话似乎就麻烦了
代码不能抛出异常,new不能抛出异常.需要手工做很多东西才行.
发表于:2007-04-27 11:41:585楼 得分:0
没有异常体系的场合仍然可以也应该大量使用raii。因为return分支仍然可能很多,你很可能在某个分支忘了释放资源。
发表于:2007-04-27 11:46:256楼 得分:0
raii是资源获取就是初始化的缩语(resource   acquisition   is   initialization),是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。

raii   的一般做法是这样的:在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
*我们不需要显式地释放资源。
*采用这种方式,对象所需的资源在其生命期内始终保持有效   ——   我们可以说,此时这个类维护了一个   invariant。这样,通过该类对象使用资源时,就不必检查资源有效性的问题,可以简化逻辑、提高效率。

--------------------------------

我知道raii是虾米,现在问题是,在没有异常支持的系统上,如何实现raii?哥们看清楚我的题目阿.

比如,构造函数中打开文件如果失败了,又没有异常,那么我该怎么返回这个错误呢?这个问题有人想过吗?
发表于:2007-04-27 11:47:177楼 得分:0
没有异常体系的场合仍然可以也应该大量使用raii。因为return分支仍然可能很多,你很可能在某个分支忘了释放资源。

那么请指教一下,raii如何实现呢?
发表于:2007-04-27 11:47:418楼 得分:0
最好能举个例子.
发表于:2007-04-27 12:00:349楼 得分:0
stl的auto_ptr就是raii的典型。
发表于:2007-04-27 12:04:2710楼 得分:0
回复人:taodm((不能收csdn社区短信息,请莫浪费精力))   (   两星(中级))   信誉:100   2007-04-27   12:00:34   得分:0
?  
stl的auto_ptr就是raii的典型。

那么没有异常支持的话,auto_ptr,能用吗?
发表于:2007-04-27 12:10:3911楼 得分:0
你自己试一下不就知道了。
发表于:2007-04-27 12:18:3012楼 得分:0
我试的结果就是不能.raii在没有异常的情况下,不能按照通常的办法去实现.

可能是我的问题问的不太明白.我要问的是,在一个没有异常支持的系统中,有方法实现raii吗?
发表于:2007-04-27 12:19:0613楼 得分:20
处理错误的方法很多,   在没有异常机制的c年代,   人们不是照样过得很好?

window编程中不是经常使用两步创建过程,   第一步...;   第二步:真正创建资源,   并返回可能的
错误.

打开文件,   我先只传一个文件名到我的raii类中,     再调用createfileptr....,   并返回可能的错误.   在raii类的释构函数中释放获得的文件(假如createfileptr成功).
   
抛出异常只不过是raii特性的一个方面.
发表于:2007-04-27 12:22:3514楼 得分:80
楼主的意思是:如果在构造函数中资源获取失败,同时又不能抛出异常,那么将来使用时这个对象将是无效的。但你有不知道错误已经发生了,使用上会有问题。是这个意思吧?
如果这样,那么可以有两种解决办法:
1、使用标志或测试函数,表明该对象是否已经正确初始化了。
2、使用两阶段对象构造,首先创建对象,然后通过对象上的一个函数执行资源获取和初始化,这个函数可以返回出错信息。当然,这种情况下,最好也提供标志或测试函数。
ms的mfc就大量采用第2种方法。因为mfc诞生的时候,c++的标准还是遥远的事。此后很长一段时间,编译器(特别是ms自己的),都不能很好地支持异常。所以,mfc被迫采取这种方案。

其实,raii的名称似乎有些误导。raii关键不在资源获取上,也就是说,不一定要在构造函数中获取资源。标准中(包括tr1)的智能指针就是一例,它们只接受你new出来的指针。自己不做内存获取。raii的关键在于类所持有的资源必须在结束生命期时通过析构函数正确释放。这才是raii保证资源安全的关键。
发表于:2007-04-27 12:41:3315楼 得分:0
楼主应该认认真真看看lidongri(海浪   源码之前了无秘密)   关于raii的介绍。
你完全概念性错误。
发表于:2007-04-27 13:27:3216楼 得分:0
raii类的构造函数中在申请资源失败的时候,通常会抛出异常.
没有人规定需要抛出异常,raai只不过是用构造和析构代替资源的获取和释放。如果资源获取不到抛出异常了,那么raii肯定会有异常;如果不抛出,则raii完全可以不抛出异常
发表于:2007-04-27 13:35:2017楼 得分:0
raii是一种 "资源封装 "方式,从本质上说和异常处理没有什么关系。非要说他们有什么关系的话,raii通常用在异常处理或者错误处理的过程中保障资源可以得到适当的释放。
发表于:2007-04-27 13:39:3518楼 得分:0
> >   stl的auto_ptr就是raii的典型。

raii   =>   resource   allocation   is   initialization

auto_ptr   根本不算真正的   raii。
发表于:2007-04-27 14:02:2719楼 得分:0
smart   pointers是隐式raii
《c.plus.plus.coding.standards.101.rules.guidelines.and.best.practices》
chapter   13   ensure   resources   are   owned   by   objects.   use   explicit   raii   and   smart   pointers

summary
don 't   saw   by   hand   when   you   have   power   tools:   c++ 's   "resource   acquisition   is   initialization "   (raii)   idiom   is   the   power   tool   for   correct   resource   handling.   raii   allows   the   compiler   to   provide   strong   and   automated   guarantees   that   in   other   languages   require   fragile   hand-coded   idioms.   when   allocating   a   raw   resource,   immediately   pass   it   to   an   owning   object.   never   allocate   more   than   one   resource   in   a   single   statement.


发表于:2007-04-27 14:37:4420楼 得分:0
我知道raii是虾米,现在问题是,在没有异常支持的系统上,如何实现raii?哥们看清楚我的题目阿.

比如,构造函数中打开文件如果失败了,又没有异常,那么我该怎么返回这个错误呢?这个问题有人想过吗?

===========================================

raii和异常没有任何必然的联系吧……应该说,只是在异常处理时,raii可以保证资源被准确的释放掉。
发表于:2007-04-27 15:24:5821楼 得分:0

这只是纯理论上的事情,   事实上,   对于不太复杂的构建,   应该极少抛出异常吧.
异常安全的代码本身就太难实现了,   看过的代码也很少见过使用异常安全的.  
不知道你们大家写代码考不考虑异常的.
发表于:2007-04-27 15:27:2122楼 得分:0
auto_ptr,   在 <c++必知必会> 上也说了是一个典型的raii,
auto_ptr <t> ptr(x);   完全吻合raii了啊,   资源获取即初始化.

不知道前面的版主怎么这么说呢
发表于:2007-04-27 16:00:1023楼 得分:0
回复人:longshanks(longshanks)   (   一级(初级))   信誉:99   2007-04-27   12:22:35   得分:0
?  
楼主的意思是:如果在构造函数中资源获取失败,同时又不能抛出异常,那么将来使用时这个对象将是无效的。但你有不知道错误已经发生了,使用上会有问题。是这个意思吧?
如果这样,那么可以有两种解决办法:
1、使用标志或测试函数,表明该对象是否已经正确初始化了。
2、使用两阶段对象构造,首先创建对象,然后通过对象上的一个函数执行资源获取和初始化,这个函数可以返回出错信息。当然,这种情况下,最好也提供标志或测试函数。
ms的mfc就大量采用第2种方法。因为mfc诞生的时候,c++的标准还是遥远的事。此后很长一段时间,编译器(特别是ms自己的),都不能很好地支持异常。所以,mfc被迫采取这种方案。

其实,raii的名称似乎有些误导。raii关键不在资源获取上,也就是说,不一定要在构造函数中获取资源。标准中(包括tr1)的智能指针就是一例,它们只接受你new出来的指针。自己不做内存获取。raii的关键在于类所持有的资源必须在结束生命期时通过析构函数正确释放。这才是raii保证资源安全的关键。

----------------------------------------------------------------

谢谢这位兄弟的指导.确实,2阶段对象构造是解决这个问题的最好方法.呵呵,看来我还需要加强文字表达能力阿.


快速检索

最新资讯
热门点击