异常,当一个函数发现一个没法处理的错误时抛出异常,让函数的ios
调用者直接或间接的处理这个问题。 数组
异常处理,是一种容许两个独立开发的程序组件在程序执行期间遇到程序不正常的ide
状况(称为异常,exception )时相互通讯的机制。函数
异常抛出:spa
throw (表达式)
异常发现与抛出异常:指针
/*发现异常而且抛出异常*/ try { //可能出现异常的语句 }
捕获异常:orm
catch(类型名 + 形参名) //捕获特定类型异常 { }
catch(...) //捕获任意类型异常(在不肯定异常类型时使用) { }
下来看一个简单的例子:对象
#include<iostream> using namespace std; int Div(int a, int b) { return a/b; } int main() { Div(1,0); system("pause"); return 0; }
结果显示:blog
程序直接崩溃,因为调用时传入第二个参数是零,零不能做除数,因此会崩溃,下面使用异常处理这个问题:内存
#include <iostream> #include <string> using namespace std; int Div(int a, int b) { if(b == 0) { throw string("parameter error.");//异常抛出 } return a/b; } int main() { try { Div(1, 0);//发现异常,与抛出异常 } catch(const string& S) { cout<<S<<endl;//捕获异常 } system("pause"); return 0; }
程序能够正常运行,也能够看到异常出现的地方,这样就能够很清楚的解决这个问题。
下面再看个了例子:
#include <iostream> #include <string> using namespace std; void test() { int* p = new int(1); if(1) { throw string("error."); } delete p; } int main() { try { test(); } catch(const string& S) { cout<<S<<endl; } system("pause"); return 0; }
结果显示:
这个程序运行貌似没有问题,其实问题大了。
void test() { int* p = new int(1); if(1) { throw string("error."); //程序执行到这里,直接就去catch()那块了, //致使new出来的内存没有释放,形成内存泄漏。 } delete p; }
内存泄漏:
会致使你开辟出来的那块内存之后就不能够用了,这样多泄漏几回,你的电脑就哈哈了,会很卡,很卡。
内存泄漏危害:
从用户使用程序的角度来看,内存泄漏自己不会产生什么危害,做为通常的用户,根本感受不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统全部的内存。从这个角度来讲,一次性内存泄漏并无什么危害,由于它不会堆积,而隐式内存泄漏危害性则很是大,由于较之于常发性和偶发性内存泄漏它更难被检测到。
固然,这里并非说内存泄漏,下面能够用异常来处理上面这个问题:
#include <iostream> #include <string> using namespace std; void test() { int* p = new int(1); try//发现异常 { if(1) { throw string("error.");//异常抛出 } } catch(...)//捕获异常 { delete p;//释放开辟的空间 throw;//异常从新抛出 } delete p; } int main() { try//发现从新抛出的异常 { test(); } catch(const string& S)//捕获异常 { cout<<S<<endl; } system("pause"); return 0; }
结果显示:
这样就不会出现内存泄漏,也会很清楚的在控制台显示错误的信息。
异常从新抛出:在异常处理过程当中也可能存在单个catch 子句不能彻底处理异常的状况。在某些修
正动做以后,catch 子句可能决定该异常必须由函数调用链中更上级的函数来处理那么catch子句能够经过从新抛出(rethrow )该异常把异常传递给函数调用链中更上级的另外一个catch子句,rethrow 表达式的形式为:
throw;
rethrow 表达式从新抛出该异常对象rethrow 只能出如今catch 子句的复合语句中。被从新抛出的对象就是其原来的异常对象。
栈展开:
在查找用来处理被抛出异常的catch 子句时由于异常而退出复合语句和函数定义这个过程
抛出异常的时候,将暂停当前函数的执行,开始查找对应的匹配catch语句。首先检查throw自己是否在catch块内部,若是是,再查找匹配的catch语句。若是有匹配的,则处理。没有则退出当前函数栈,继续在调用函数的栈中进行查找。不断重复上述过程。若到达main函数的栈,依旧没有匹配的,则终止程序。
上述这个沿着调用链查找匹配的catch语句的过程称为栈展开。找到匹配的catch语句并处理之后,会继续沿着catch语句后继继续执行。
异常捕获的匹配规则:
异常对象的类型与catch说明符的类型必须彻底匹配。
只有如下几种状况例外:
1. 容许从非const对象到const的转换。
2. 容许从派生类型到基类类型的转换。
3. 将数组转换为指向数组类型的指针,将函数转换为指向函数类型的指针。
异常处理总结:
异常处理就是经过throw,try,catch,这三个关键字,来发现异常,并抛出异常,捕获异常,能够作出相应的处理。(这只是简单的异常处理)