现在的位置: 首页 > 综合 > 正文

合理使用c++异常处理机制

2018年02月15日 ⁄ 综合 ⁄ 共 2896字 ⁄ 字号 评论关闭

c++提供了异常处理机制。

它的优点:

(1)正常流程与异常流程分开处理。逻辑上更清晰。

(2)不使用异常机制,就要在调用函数堆栈中一系列函数中编写大量判断语言,干扰正常流程逻辑。

实际测试代码 

见 http://blog.csdn.net/zjplus/article/details/2541143

//normal.cpp
#include <iostream>
#include <ctime>

using namespace std;


void normal(const int count)
{
	long k = 0;
	clock_t start = clock();

	for (int j=0; j<count; j++)
	{
		k++;
		k = k % count;
	}

	clock_t end = clock();
	double last_time = double(end - start) / CLOCKS_PER_SEC;
	cout<<"normal() last time is "<<last_time<<endl;
	cout<<k<<endl;         // 防止for循环被优化了
}

int main(int argc, char **argv)
{
	int count = 50000000;

	normal(count);

	cin.get();
	return 0;

};

//try_with_no_exception.cpp
#include <iostream>
#include <ctime>
using namespace std;

void try_with_no_exception(const int count)
{
	long k = 0;
	clock_t start = clock();

	for (int j=0; j<count; j++)
	{
		try
		{
			k++;
			k = k % count;
		}
		catch (int e)
		{
			/// do nothing
		}
	}

	clock_t end = clock();
	double last_time = double(end - start) / CLOCKS_PER_SEC;
	cout<<"try_with_no_exception() last time is "<<last_time<<endl;
	cout<<k<<endl;         // 防止for循环被优化了
}

int main(int argc, char **argv)
{
	int count = 50000000;
	try_with_no_exception(count);
	cin.get();
	return 0;
};

//try_with_exception.cpp
#include <iostream>
#include <ctime>
using namespace std;

void try_with_exception(const int count)
{
	long k = 0;
	clock_t start = clock();
	for (int j=0; j<count; j++)
	{
		try
		{
			k++;
			k = k % count;
			throw 10;
		}
		catch (int e)
		{
		/// do nothing
		}
	}
	clock_t end = clock();
	double last_time = double(end - start) / CLOCKS_PER_SEC;

	cout<<"try_with_exception() last time is "<<last_time<<endl;
	cout<<k<<endl;         // 防止for循环被优化了
}
int main(int argc, char **argv)
{
	int count = 5000;
	try_with_exception(count);
	cin.get();
	return 0;
};

时间对比
函数名 是否开启异常 循环次数 时间(s)
normal 五千万次 0.985
normal 五千万次 0.985
try_with_no_exception 五千万次 1.016
try_with_exception.cpp 五万次 38.078

由对比数据可得出如下结论

运行带有异常的代码函数,当不抛出异常时,其运行效率与没有异常代码的函数,效率上几乎没有差别。

运行时大量抛出异常会严重影响程序效率。

所以,若在c++使用异常,则要示使用异常机制的代码,执行概率要非常小。

附:

google 的c++异常的观点

不要使用C++异常。 

优点: 1) 异常允许上局应用决定如何处理在底局嵌套函数中収生的“不可能发生”的失败,不像出错代码的记彔那么模糊费解;

 2) 应用亍其他徆多现代语言中,引入异常使得C++与Python、Java及其他与C++相近的语言更加兼容;

 3) 许多C++第三方库使用异常,关闭异常将导致难以与之结合; 

4) 异常是解决构造函数失败的唯一方案,虽然可以通过工厂函数(factory function)或Init()方法模拟异常,但他们分别需要堆分配新的“非法”状态;

 5) 在测试框架(testing framework)中,异常确实很好用。

 缺点: 1) 在现有函数中添加throw语句时,必须检查所有调用处,即使它们至少具有基本的异常安全保护,或者程序正常结束,永迖不可能捕获该异常。

例如:如果f()依次调用了g()和h(),h抛出被f捕获的异常,g就要当心了,避免没有完全清理;

 2) 通俗一点说,异常会导致程序控制流(control flow)通过查看代码无法确定:函数有可能在不确定的地方返回,从而导致代码管理和调试困难,当然,你可以通过规定何时何地如何使用异常来最小化的降低开销,却给开发人员带来掌撑这些规定的负担;
3) 异常安全需要RAII和不同编码实践。轻松、正确编写异常安全代码需要大量支撑。允许使用异常;

 4) 加入异常使二进制执行代码体积变大,增加了编译时长(或许影响不大),还可能增加地址空间压力; 

5) 异常的实用性可能会刺激开发人员在不恰当的时候抛出异常,或者在不安全的地方从异常中恢复,例如,非法用户输入可能导致抛出异常。如果允许使用异常会使得返样一篇编程风格指南长出很多(译者注,返个理由有点牵强)

 结论: 从表面上看,使用异常利大亍弊,尤其是在新项目中,然而,对亍现有代码,引入异常会牵还到所有依赖代码。如果允许异常在新项目中使用,在跟以前没有使用异常的代码整合时也是一个麻烦。因为Google现有的大多数C++代码都没有异常处理,引入带有异常处理的新代码相当困难。 鉴于Google现有代码不接受异常,在现有代码中使用异常比在新项目中使用的代价多少要大一点,迁移过程会比较慢,也容易出错。我们也不相信异常的有效替代方案,如错误代码、断言等,都是严重负担。 我们并不是基于哲学或道德局面反对使用异常,而是在实践的基础上。因为我们希望使用Google上的开源项目,但项目中使用异常会为此带来不便,因为我们也建议不要在Google上的开源项目中使用异常,如果我们需要把返些项目推倒重来显然不太现实。
对于Windows代码来说,这一点有个例外(等到最后一篇吧:D)。 注:对于异常处理,显然不是短短几句话能够说清楚的,以构造函数为例,很多C++书籍上都提到当构造失败时只有异常可以处理,Google禁止使用异常返一点,仅仅是为了自身的方便,说大了,无非是基亍软件管理成本上,实际使用中还是自己决定。

抱歉!评论已关闭.