<b>C++非常和错误处理经验谈</b>[VC/C++编程]
本文“<b>C++非常和错误处理经验谈</b>[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
替换 try / catch / throw 的普通做法是返回一个返回代码(有时称为错误代码),比方,printf(), scanf() 和 malloc()就是这样工作的:调用者通过if等语句来测试返回值判断函数能否成功.
固然返回代码技术有时是最得当的错误处理技术,但会增添不必要的if语句这样的令人讨厌的效果.
质量降级:众所周知,条件语句大概包含的错误大约十倍于其他范例的语句.因此,在其他都相同时,假如你能从代码中消除条件语句,你会得到更结实的代码.
推迟面市:由于条件语句是分支点,而它们关系到白盒法测试时的测试条件的个数,因此不必要的条件语句会增添测试的时间总量.假如你没有走过每个分支点,那么你的代码中就会有在测试中没有被履行过的指令,直到用户/客户发现它,那就糟糕了.
增添开辟本钱:不必要的掌握流程的复杂性增添了探求bug,修复bug,和测试的工作.
因此,相关于通过返回代码和if来报告错误,利用try / catch / throw所产生更少有bug,更低的开辟本钱和更快面市的代码.
若何处理构造函数的失利?
构造函数没有返回范例,所以返回错误代码是不大概的.因此抛出非常是标志构造函数失利的最好办法.
假如你没有大概不肯意利用非常,这里有一种办法.假如构造函数失利了,构造函数可以把对象带入一种“僵尸”状况.你可以通过设置一个内部状况位使对象就象死了一样,即便从技术上来说,它仍旧活着.然后加入一个查询(“查察员”)成员函数,以便类的用户可以通过查抄这个“僵尸位”来肯定对象是真的活着还是已经成为僵尸(也就是一个“活着的死对象”).你大概想有另一个成员函数来查抄这个僵尸位,并且当对象并非真正活着的时刻,履行一个 no-op(大概是更令人讨厌的如 abort()).这样做真的不漂亮,但是假如你不能(大概不想)利用非常的话,这是最好的办法了.
若何处理析构函数的失利?
往log文件中写一个消息.但不要抛出非常!
C++的法则是你绝对不可以在另一个非常的被称为“栈展开(stack unwinding)”的历程中时,从析构函数抛出非常.举例来说,假如某人写了throw Foo(),栈会被展开,以至throw Foo()和 } catch (Foo e) { 之间的全部的栈页面被弹出.这被称为栈展开(statck unwinding)
在栈展开时,栈页面中的全部的部分对象会被析构.假如那些析构函数之一抛出非常(假定它抛出一个Bar对象),C++运行时系统会处于无法决断的际遇:应当忽视Bar并且在} catch (Foo e) { 完毕?应当忽视Foo并且探求 } catch (Bar e) { ?没有好的答案——每个挑选城市丧失信息.
因此C++语言担保,当处于这一点时,会调用terminate()来杀死进程.忽然死亡.
避免这种情形的简单办法是不要从析构函数中抛出非常.但假如你真的要聪明一点,你可以说"当处理另一个非常的历程中时,不要从析构函数抛出非常".但在第二种情形中,你处于艰难的地步:析构函数本身既需求代码处理抛出非常,还需求处理一些“其他东西”,调用者没有当析构函数检测到错误时会发生什么的担保(大概抛出非常,也大概做一些“其他事情”).因此完好的办理筹划非常难写.因此干脆就做一些“其他事情”.也就是,不要从析构函数中抛出非常.
当然,由于总有一些该法则无效的景况,这些话不该该被“引证”.但至少99%的情形下,这是一个好法则.
假如构造函数会抛出非常,我该怎样处理资源?
对象中的每个数据成员应当清理自己.
假如构造函数抛出非常,对象的析构函数将不会运行.假如你的对象需求撤消一些已经做了的行动(如分配了内存,翻开了一个文件,大概锁定了某个信号量),这些需求被撤消的行动必须被对象内部的一个数据成员记着.
比方,应当将分配的内存赋给对象的一个“智能指针”成员对象Fred,而不是分配内存给未被初始化的Fred* 数据成员.这样当该智能指针灭亡时,智能指针的析构函数将会删除Fred对象.尺度类auto_ptr就是这种“智能指针”类的一个例子.你也可以写你自己的引用计数智能指针.
当别人抛出非常时,我若何改变字符数组的字符串长度来避免内存泄露?
假如你要做的确切需求字符串,那么不要利用char数组,因为数组会带来麻烦.应当用一些近似字符串类的对象来替换.
以上是“<b>C++非常和错误处理经验谈</b>[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |