如何编写异常安全的C++代码

如何编写异常安全的C++代码,第1张

如何编写异常安全的C++代码,第2张

关于C++中的异常有很多争论,但往往是一些不成立的误解。异常曾经是一个很难用好的语言特性。幸运的是,随着C++社区经验的积累,今天我们有足够的知识来轻松编写异常安全的代码,编写异常安全的代码一般不会影响性能。使用异常还是返回错误代码?这是一个有争议的话题。你一定听过这样一句话,异常只有在真正异常的情况下才会使用。什么是“真正不正常的时间”?在回答这个问题之前,我们先来看看编程中的不变性原理。
对象是属性聚合加方法。如何确定一个对象的属性聚合是否处于逻辑正确的状态?这可以通过一系列的断言来完成,最后下一个结论就是这个对象的属性聚合在逻辑上是正确的还是有问题的。这些断言是度量对象属性集合的不变量。
我们通常在函数调用中检查不变量。不变量分为前置条件、后置条件和不变量三类。前置条件是指函数被调用前必须满足的逻辑条件,后置条件是函数被调用后必须满足的逻辑条件,不变量是整个函数执行过程中必须满足的条件。在我们的讨论中,不变量既是前置条件又是后置条件。前一个条件必须满足,如果不满足,就是程序逻辑错误,后一个条件不一定。现在,我们可以用不变量来严格定义异常情况:如果前置条件满足,但后置条件不能满足,就是异常情况。且只有当异常情况发生时,才会抛出异常。
关于何时抛出异常的回答中,不排除返回值报错,两者是正交的。然而,从我们的经验来看,我们可以在两者之间进行选择。为什么?事实上,当我们做出这种选择时,必然意味着界面的语义变化。不改变接口,我们实际上无法选择(尝试用返回值处理构造函数中的错误)。通过用不变量区分正常和异常情况,可以更好地细化接口。
异常安全的评估分为基本保障、强保障、无故障三个级别。
基本保证:保证程序(对象)在异常发生时处于未知但有效的状态。有效,即对象的所有不变检查都通过。
强保证:保证操作的事务性,要么成功,程序处于目标状态,要么不改变。
不会失败:对于大多数函数来说,这很难保证。对于C++程序,至少析构函数、释放函数、交换函数要保证不会失败,这是编写异常安全代码的基础。
首先从非正常情况下的资源管理问题说起。可能很多人都这样做过:
Type * obj = new Type;
尝试{做某事...}
catch(...){删除对象;扔;}
不要这样!这样做只会让你的代码看起来混乱,而且会降低效率,这也是它一直名声不好的原因之一。请使用RAII技术来做到这一点:
auto _ ptr obj _ ptr(new Type);做某事...
这样的代码简洁、安全、高效。当你不关心或者不能处理异常时,请不要试图去捕捉它。它没有使用try...catch编写异常安全的代码,并且大多数异常安全的代码不需要尝试...接住。我承认现实世界并不总是像上面的例子那么简单,但是这个例子确实可以代表很多非正常安全代码的做法。在这个例子中,boost::scoped_ptr是auto_ptr更合适的替代。
现在考虑这样一个构造函数:
Type (): m_a (newtypea),m_b (newtypeb) {}
假设成员变量m_a和m_b是原始指针类型,并且它们与类型中声明的顺序一致。这种代码是不安全的,它有资源泄露的问题,而构造函数的失败回滚机制无法应对这个问题。如果new TypeB抛出异常,new TypeA返回的资源就不能释放。曾经,很多人用这种方法来避免异常:
type (): m _ a (null),m _ b(null){
auto _ ptr tmp _ a(new typea);
auto_ptr tmp_b(新类型b);
m _ a = tmp _ a . release();
m _ b = tmp _ b . release();
}
当然,这种方法确实可以实现异常安全的代码,实现思路会很重要。在如何实现具有强保证的异常安全代码时,将采用这种思想。然而,这种方法不够彻底,至少析构函数必须手动完成。我们还是可以借助RAII技术更彻底的做到这一点:shared _ ptr m _ a;shared _ ptr m _ b;这样我们就可以很容易的写出异常安全的代码:
Type (): M _ A (newtypea),M _ B (newtypeb) {}
如果你觉得shared_ptr的性能达不到要求,可以写一个智能指针类,接口类似scoped_ptr,释放析构函数里的资源就可以了。如果类被设计成不可复制的,你也可以直接使用scoped_ptr。强烈建议不要将auto_ptr用作数据成员。scoped_ptr名字不好,但至少是安全的,不会引起混淆。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 如何编写异常安全的C++代码

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情