文章目录
- 异常
- 概念
- 异常抛出与捕获
- 栈展开
- 重新抛出异常
- 异常规范
异常
概念
异常处理机制允许程序在运行时发现异常后抛出一个对象,会包含比c语言的错误码更全面的信息
抛出异常后会跳过后面的部分,跳转到异常处理模块
异常抛出与捕获
程序出现问题时会throw一个异常对象,该对象的类型及当前调用链决定由哪个catch处理该异常
throw执行后,throw后面的语句不再执行,跳转到与之匹配的catch代码块
异常对象可能是局部变量,所以还会生成一个异常对象的拷贝,并在在catch代码块执行完后销毁
catch只能捕获类型匹配的异常,如果一个异常有多个匹配的catch,就会被最近的那个捕获
栈展开
抛出异常后,程序会暂停当前函数,寻找catch
先检查throw有没有在try块内部,在的话就寻找try对应的catch 如果当前函数中没有try或者try和catch不匹配,则退出当前函数,返回外层函数中查找,称之为栈展开 如果展开到了main函数仍然没有catch,就会终止程序,所以一般在main函数最后都会使用一个catch(...),它会捕获任意类型的异常,但是不读取voidfunc2(){throw"error";//抛出异常}voidfunc3(){throw404;}voidfunc1(){func2();//异常向上抛,触发栈展开func3();//也会抛出异常}intmain(){try{func1();}catch(conststring&e)//通过string&来捕获异常{cout<<"捕获string异常:"<<e<<endl;}catch(inte)//通过int类型来捕获异常{cout<<"捕获int异常:"<<e<<endl;}catch(...){cout<<"捕获未知异常"<<endl;}return0;}重新抛出异常
在catch中直接throw,不写异常对象,会将捕获的异常再次抛出
异常规范
如果一段函数后面加了noexcept,表示该函数不会抛出异常,如果它里面又写了throw,会导致程序终止
noexcept(表达式)也可以用于判断一段表达式是否会抛出异常,返回值为bool
异常很容易导致死锁,在前面拿到了锁,后面抛出异常后跳过了,没有归还锁,可以通过catch手动解锁,但更推荐RAII自动处理
voidfunc(){try{throwstring("抛出异常");}catch(conststring&e){cout<<"内层捕获:"<<e<<endl;throw;// 重新抛出,交给外层处理}}intmain(){try{inta=0;boolres=noexcept(a=2);//赋值表达式,一定不会抛出异常,res=truefunc();}catch(conststring&e){cout<<"外层捕获:"<<e<<endl;}return0;}