C++异常处理相关用法及底层机制

本文详细介绍了C++中的异常处理,包括异常的定义、基本使用方式、异常处理机制和实现原理。通过实例展示了如何抛出和捕获异常,强调了异常处理在确保程序健壮性方面的重要性,并探讨了在构造函数中处理异常的方法。此外,还提到了`noexcept`异常说明以及异常类的使用。
摘要由CSDN通过智能技术生成
一、异常的定义及C++中的异常处理

异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。

异常检测: 当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。

异常处理: 如果程序中含有可能引发异常的代码,那么通常也会有专门的代码处理问题。异常处理部分就是用来对捕获的异常进行处理的。

异常处理机制: 为程序中异常检测和异常处理这两部分的协作提供支持。

在C++中,异常处理包括:

  • throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。throw引发了异常

  • try-catch语句块,异常处理部分使用try-catch语句块处理异常。try{}后以一个或多个catch(){}子句结束,try{}中的代码抛出的异常通常会被某个catch子句处理。catch子句通常被称为异常处理代码。catch(…)意为捕获所有异常,如果有多个catch子句,catch(…)必须放在最后,否则后面的catch语句不可能得到执行。

  • 异常类,用于在throw表达式和相关的catch子句之间传递异常的具体信息。


二、异常的基本使用方式

所需头文件

#include<exception>    //定义了最通用的异常类exception,只报告异常的发生,不提供任何额外信息
#include<stdexcept>    //定义了几种最常用的exception类

抛出异常

void fun(){
   
    ···;
    throw runtime_error("xx error!");//抛出异常
    ···;
}

捕获异常

try{
   //try语句块中调用的fun()函数抛出异常
    fun();
}catch(runtime_error& e){
   //捕获runtime_error异常
    cout<<e.what()<<endl;//打印异常错误信息
}

三、异常处理
作用

​异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理。异常能使得我们能够将问题的检测与解决过程分离开来。程序的一部分负责检测问题的出现,另一部分负责问题的解决。

(1)抛出异常

​C++中通过throw表达式来引发(raised)异常,被抛出的表达式的类型(即异常类型)以及当前函数调用链共同决定了哪段处理代码(handler,即哪个try-catch块)将被用来处理该异常。

​当执行一个throw时,跟在throw后面的语句将不再被执行。程序的控制权从throw转移到与之最先匹配到的catch模块。这会引发两个后果:

  • catch至throw之间的所有函数提早退出
  • 被退出的函数内的对象将被销毁

​抛出一个异常后,程序将暂停当前函数的执行过程,并寻找与之匹配的catch子句。将会沿着函数调用链从内到外逐步检查,如果throw语句或调用该throw语句的函数或在该throw语句的调用链上的函数在try语句块内,且该try子句对应的catch子句中存在对该异常的处理,则程序进入该catch子句并从这里开始继续执行。这个过程被称为栈展开,即从最内层函数逐步向外层展开,直到找到匹配的catch语句或到最外层还没有找到匹配。如果一直到main函数还没有找到匹配的catch子句,程序将会调用标准库中的terminate函数,终止程序的执行。

​在栈展开的过程中,将沿着函数调用链逐步向外,内层的函数将会退出,这些函数中的局部对象将会被随之销毁。对于内置对象(int,double等),编译器无需任何操作,因为找到匹配的catch块后程序的函数栈将会退栈,调用链上的栈帧将会被销毁,这些对象自然失去了意义,也不会再被访问到。对于类对象而言,将会自动执行析构函数,具体原理后面将会介绍。对于动态分配的指针,退栈后无法再得到这些指针,因此没有办法找到相应的动态分配内存,会造成内存泄漏的问题。因此对于动态分配相关的资源管理问题,最好用类来管理,例如用构造函数new,析构函数delete,或直接使用智能指针。

以下是一个例子,可以看出异常处理链的执行情况以及类对象析构情况。

#include<iostream>
#include<stdexcept>
#include<memory>
using namespace std;
//A调用B,B调用C,C抛出异常,B catch所有异常并全部抛出,A捕获异常
void funA();
void funB();
void funC();

class ClassA
{
   
public:
	ClassA():pi(new int[len]) {
    cout <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值