冰冰学习笔记:异常处理

news2025/5/19 13:30:13

欢迎各位大佬光临本文章!!!

 

还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正。

本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬、帅哥、美女点点支持,您的每一分关心都是我坚持的动力。

我的博客地址:bingbing~bang的博客_CSDN博客https://blog.csdn.net/bingbing_bang?type=blog

我的gitee:冰冰棒 (bingbingsupercool) - Gitee.comhttps://gitee.com/bingbingsurercool


系列文章推荐

冰冰学习笔记:《位图与布隆过滤器》

冰冰学习笔记:《C++11的新特性》


目录

系列文章推荐

前言

1.C语言的传统处理与异常

2.异常的使用

2.1异常的抛出和捕获

2.2异常的重新抛出

2.3异常的安全和异常规范 

3.标准库提供的异常类

4.异常的优缺点


前言

        异常处理是C++对于代码运行错误的一种处理方式,与C语言的处理方式不同,异常处理并没有C语言的果断与强制,异常的处理显得更加柔和,只会影响部分代码无法运行,对于整体的逻辑并没有太大的影响。

1.C语言的传统处理与异常

        C语言传统的错误处理机制是抛出错误码或者程序崩溃,对于某些函数调用出错,函数会返回特定的返回值,并且设置错误码。这种处理方式的排错会比较复杂,对于调用层次很深的函数出错,错误码会层层返回,直到最外层才能进行处理。程序崩溃更是非常严重的影响,例如某一块程序发生内存错误,assert断言会直接触发导致程序崩溃,整个进程都会退出,照成很大的后果。

        C++认为此种错误的处理方式太过于激进,程序某个模块的错误就有可能导致整体出现崩溃,对于长期运行的服务器来说,这是无法接受的情况。因此C++设置了异常处理机制,异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。

异常的实现需要使用三个关键字:

throw:当问题出现时,程序会抛出一个异常,通过关键字throw完成。

catch:在你想要处理问题的地方,通过异常处理程序捕获异常,可以包含多个catch语句。

try:try块中的代码将会运行,为可能出现异常的代码。在出现异常时将被后面的catch捕获。

因此异常的基本方式如下所示:

double Div(int x, int y)
{
	if (y == 0)
		throw"Division by zero condition!";//抛出字符串类型的错误
	else
		return x / y;
}
int main()
{
	try
	{
		double ret=Div(10, 0);
	}
	catch(const char* message)//捕捉字符串类型
	{
		cout << message << endl;
	}
	catch (...)//捕捉任意类型的错误
	{
		cout << "unknow exception" << endl;
	}
	return 0;
}

2.异常的使用

2.1异常的抛出和捕获

异常的使用和捕获需要遵循一些原则。

(1)异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。

(2)被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。

(3)抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象, 所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的传值返回)。

(4)catch(...)可以捕获任意类型的异常,问题是不知道异常错误是什么。

(5)实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象, 使用基类捕获。

函数调用链中异常栈展开匹配原则

(1)首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。如果有匹配的,则调到catch的地方进行处理

(2)没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。

(3)如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的 catch子句的过程称为栈展开。所以实际中我们最后都要加一个catch(...)捕获任意类型的异 常,否则当有异常没捕获,程序就会直接终止。

(4)找到匹配的catch语句并处理以后,会继续沿着catch子句后面继续执行。

int Func2(int x)
{
	if (x < 0)
		throw "x<0";
	if (x == 0)
		throw x;
	return x;
}
int Func1(int x,int y)
{
	try
	{
		if (x == 0)
		{
			throw x;
		}
		if (y == 0)
		{
			throw "y==0";
		}
		Func2(x - y);
		return x + y;
	}
	catch (const char* ch)
	{
		cout << ch << endl;
	}
}
int main()
{
	try {
		Func1(2,2);
	}
	catch(int x)
	{
		cout << "x的值: "<<x << endl;
	}
	catch (const char* ch)
	{
		cout << ch << endl;
	}
	catch (...)
	{
		cout << "unkonw exception" << endl;
	}
	return 0;
}

        例如上面的一段测试代码如果Func1函数的参数为0,1。那么Func1函数将抛出整型值x,catch语句将会匹配int x,最终打印出x的值。这就是最佳匹配原则,而Func2函数的参数为-1,会抛出"x<0"的字符串,由于Func1函数中具备该类型的捕获,那么就会直接在Func1函数中进行异常的处理。 如果Func1函数的参数为2,2,那么Func2函数的参数将会变为0,此时函数将会抛出整形值x,但是Func2没有catch语句进行错误的捕获,将返回给调用层Func1函数,但是Func1函数的异常捕获并没有整形类型的捕获,此时异常将继续向上一层返回,直到main函数进行异常的捕获,如果main函数也没有进行异常的捕获,那么程序将会崩溃。

2.2异常的重新抛出

        当异常被catch语句捕获后,有可能该catch并不能完全处理一个异常,在进行一些处理后,希望交给外层的调用链函数来处理,catch语句块中可以将异常重新抛出。

2.3异常的安全和异常规范 

        构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不 完整或没有完全初始化。析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏。

        C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄 漏,在lock和unlock之间抛出了异常导致死锁,C++经常使用RAII来解决以上问题。

        异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。 可以在函数的后面接throw(类型),列出这个函数可能抛掷的所有异常类型。 函数的后面接throw(),表示函数不抛异常。若无异常接口声明,则此函数可以抛掷任何类型的异常。

// 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void fun() throw(A,B,C,D);
// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw();
// C++11 中新增的noexcept,表示不会抛异常
thread() noexcept;
thread (thread&& x) noexcept;

        在实际使用中异常规范并没有很多的作用,因为并非是强制使用,所以很少会有人遵守该规范。并且对于该规范来说,有时我们对某些函数添加了说明,表示该函数不会抛出异常,但是在实际使用中有可能会抛出一些不知名的异常,这就导致程序错误。

3.标准库提供的异常类

        实际上在日常的应用中,往往都会定义自己的异常体系来方便管理,因为如果一个项目中大家的异常随意抛出,外层的调用者基本无法进行捕获,但是我们定义一个异常类,抛出者抛出子类,外层使用基类进行接收即可。

实际上C++库中为我们提供了标准的异常类:

 

 我们可以直接继承该类型的类创建自己的异常类,但是公司一般喜欢自己创建异常体系。

4.异常的优缺点

 异常的优点:

(1)异常对象定义好了,相比错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包 含堆栈调用的信息,这样可以帮助更好的定位程序的bug。

(2)返回错误码的传统方式有个很大的问题就是,在函数调用链中,深层的函数返回了错误,那 么我们得层层返回错误,最外层才能拿到错误,具体看下面的详细解释。

(3)很多的第三方库都包含异常,比如boost、gtest、gmock等等常用的库,那么我们使用它们 也需要使用异常。

(4)部分函数使用异常更好处理,比如构造函数没有返回值,不方便使用错误码方式处理。比如 T& operator这样的函数,如果pos越界了只能使用异常或者终止程序处理,没办法通过返回 值表示错误。

异常的缺点:

(1)异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。这会 导致我们跟踪调试时以及分析程序时,比较困难。

(2)异常会有一些性能的开销。当然在现代硬件速度很快的情况下,这个影响基本忽略不计。

(3) C++没有垃圾回收机制,资源需要自己管理。有了异常非常容易导致内存泄漏、死锁等异常 安全问题。这个需要使用RAII来处理资源的管理问题。学习成本较高。

(4)C++标准库的异常体系定义得不好,导致大家各自定义各自的异常体系,非常的混乱。

(5).异常尽量规范使用,否则后果不堪设想,随意抛异常,外层捕获的用户苦不堪言。所以异常 规范有两点:一、抛出异常类型都继承自一个基类。二、函数是否抛异常、抛什么异常,都 使用 func() throw();的方式规范化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Github-Action-Workflow-概念和基本操作

workflow 文件 GitHub Actions 的配置文件叫做 workflow文件&#xff0c;存放在代码仓库的.github/workflows/目录下。比如写一个first.yaml文件&#xff0c;存储的目录就是.github/workflows/first.yaml workflow/下的文件采用 YAML 格式&#xff0c;文件名可以任意取&#xf…

代码随想录第56天|● 583. 两个字符串的删除操作 ● 72. 编辑距离

583.两个字符串的删除操作 思路一 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元素的最少次数。 当word1[i - 1] 与 word2[j - 1]相同的时候 dp[i][j] dp[i - 1][j - 1];当word1[…

检修盒面板AI视觉检测系统,赋能工业发展!

制造业是中国工业化的源头&#xff0c;也是工业生产大国。任何一步的质量都可能影响生产过程的变化。表面缺陷不仅影响产品的美观和舒适性&#xff0c;还会对其性能产生不良影响。因此&#xff0c;制造商对产品的表面缺陷检测非常重视。传统的检修盒面板按钮安装是否正确的质量…

【深度学习】CNN应用于图像分类的建模全流程

文章目录1.摘要2.图片的准备及预处理3.打包并保存数据4.搭建模型5.训练模型6.测试模型7.总结1.摘要 图像分类&#xff0c;也可以称作图像识别&#xff0c;顾名思义&#xff0c;就是辨别图像中的物体属于什么类别。核心是从给定的分类集合中给图像分配一个标签的任务。实际上&a…

DBeaver连接InterSystems IRIS、Ensemble、Cache操作说明

一、驱动获取 1.1、本地安装目录获取 JDBC驱动&#xff1a;“安装目录\dev\java\lib\JDK18” 如需获取ODBC等其他连接驱动则返回“安装目录\dev”路径选择对应文件夹2.1、Intersystems官方获取 官方下载&#xff1a;https://intersystems-community.github.io/iris-driver-…

深度学习基本部件-激活函数详解

激活函数概述 前言激活函数定义激活函数性质 Sigmoid 型函数 Sigmoid 函数Tanh 函数 ReLU 函数及其变体 ReLU 函数Leaky ReLU/PReLU/ELU/Softplus 函数 Swish 函数激活函数总结参考资料 本文分析了激活函数对于神经网络的必要性&#xff0c;同时讲解了几种常见的激活函数的原理…

纸牌游戏红心大战拱猪设计(C语言)

纸牌游戏红心大战设计 ( C语言 ) 红心大战是Windows的经典游戏&#xff0c;中国式的红心是拱猪游戏&#xff0c;加入了方块J羊和梅花10 变压器&#xff08;即俗称加倍&#xff09;。加大了游戏难度和趣味性。 试制此游戏是准备编制网络版拱猪或红心大战的基础框架&#xff0c…

Linux下时间处理相关函数

Linux下时间处理相关函数 1 .系统时间和 RTC 时间 Linux 系统下包含两个时间&#xff1a; 系统时间和 RTC 时间。   系统时间&#xff1a; 是由主芯片的定时器进行维护的时间&#xff0c; 一般情况下都会选择芯片上最高精度的定时器作为系统时间的定时基准&#xff0c; 以避…

深度聚类方法之对比聚类(Contrastive Clustering,CC)

1.参考文献 《Contrastive Clustering》 2.深度聚类方法 深度聚类方法大致分为以下几类&#xff1a; ①分阶段&#xff1a;使用深度网络进行对比学习or自动编码器完成表征学习(目的&#xff1a;把同类样本集中到一起&#xff0c;拉开不同类样本的聚类)&#xff0c;然后使用聚…

【6】SCI易中期刊推荐——人工智能神经科学机器人学(中科院3区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

头条某星图 登录协议解析2023/1/9

文章目录 文章目录 文章目录前言网址加密字段请求逻辑生成s_v_web_id账号密码的加密方式fp滑块登录成功前言 可以关注我哟,一起学习,主页有更多练习例子 如果哪个练习我没有写清楚,可以留言我会补充 如果有加密的网站可以留言发给我,一起学习共享学习路程 如侵权,联系我删…

【JavaGuide面试总结】Java高级特性基础篇·下

【JavaGuide面试总结】Java高级特性基础篇下1.什么是序列化?什么是反序列化?2.序列化协议对应于 TCP/IP 4 层模型的哪一层&#xff1f;3.常见序列化协议有哪些&#xff1f;4.为什么不推荐使用 JDK 自带的序列化&#xff1f;5.如果有些字段不想进行序列化怎么办&#xff1f;6.…

梦幻西游H5私服服务端超详细图文架设教程

想体验经典Q版西游霸服高兴吗&#xff1f;想体验满级VIP的尊贵吗&#xff1f;想体验一招秒杀的痛快吗&#xff1f;各种极品配备、翅膀、宠物统统给你&#xff0c;就在梦幻西游&#xff01;本文解说梦幻西游H5游戏的架设教程&#xff0c;想钻研H5游戏如何实现&#xff0c;体验游…

基于Python实现的车辆检测计数+车牌定位+车牌识别的融合技术,使用pytorch深度学习框架

车辆检测计数车牌检测与车牌识别 介绍 基于pytorch深度学习框架&#xff0c;实用开源模型yolov4实现模板检测与yolov5实现车牌检测与LPRNet实现车牌检测 完整代码下载地址&#xff1a;基于Python实现的车辆检测计数车牌定位车牌识别的融合技术 基于win10系统&#xff0c;实用…

JSP SSM加班管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP SSM加班管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和 数据库&#xff0c;系统主要采用B/…

python数据分析及可视化(十九)Power BI中M函数的使用、数据建模、度量值、DAX

M函数 用鼠标操作的步骤背后的逻辑都是M函数&#xff0c;在编辑器里都会有体现出来&#xff0c;选中左侧的表名称&#xff0c;点击右键&#xff0c;选择高级编辑器&#xff0c;就会进入到高级编辑器界面&#xff0c;里面会显示每一步的操作步骤。 M函数基本规范 M函数对大小写…

常用JavaScript库

1、前端工具类库 jQuery是一个快速、小型且功能丰富的 JavaScript 库&#xff0c;它使HTML文档遍历和操作、事件处理、动画和 AJAX 之类的事情变得更加简单。当时jQuery库不但简化了代码&#xff0c;而且提供出色的跨浏览器支持&#xff0c;其极大的提高了 Web 开发人员的工作效…

sqlserver连接时报错 [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序

电脑重新安装系统了&#xff0c;当我再次链接数据库时 &#xff0c;发现报错 [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序很明显是少了驱动&#xff0c;只要安装了Microsoft ODBC Driver 11 for SQL Server这个驱动就可以了。 没安装驱动…

实时性升至秒级!飞桨PaddleSpeech赋能金融双录业务走向智能化

听说IT圈十个人里有九个是男性开发者&#xff0c;女生并不多&#xff0c;陈雪儿可以算是这个群体中独特的存在。 作为杭州谐云科技有限公司&#xff08;简称谐云&#xff09;智能边缘团队的AI技术专家&#xff0c;陈雪儿带领团队历经一年半研发的“金融双录智能质检系统”&…

功率放大器怎么选择型号的(功率放大器选购技巧)

很多电子工程师虽然频繁使用功率放大器&#xff0c;但是对于功率放大器的选择和选购技巧还是不清楚&#xff0c;下面就来为大家介绍一下如何挑选合适的功率放大器型号。 一般情况下&#xff0c;功率放大器购买决策的主要考虑因素是输出功率、线性度、频率范围和VSWR失配容限。放…