C++程序设计——异常
一、C++异常概念
异常处理是一种处理错误的方式,当一个函数发现自己无法处理的错误时,就可以抛出异常,让函数的直接或间接的调用者处理这个错误。
(1)throw:当问题出现时,程序会通过throw关键字抛出异常。
(2)catch:在想要处理问题的地方,异常处理程序通过catch关键字捕获异常,可以有多个catch进行捕获。
(3)try:try块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个catch块。
二、异常的使用
1.异常的抛出和捕获
1.1 异常的抛出和匹配原则
(1)异常是通过抛出对象而引发的,该对象的类型决定了应该激活那个catch的处理代码,即catch捕获的异常类型必须与throw抛出的异常实体类型完全一致,因为这里编译器基本不会进行隐式类型转换。
(2)被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的哪一个。
(3)抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所有会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。
(4)catch(...)可以捕获任意类型的异常,但问题是不知道异常错误是什么。
(5)实际中抛出和捕获的匹配原则有个例外:一般不会发生隐式类型转换,类型都是完全匹配,但是有一个例外,就是可以抛出派生类对象,使用基类捕获,在实际中非常实用。
1.2 函数调用链中异常栈展开匹配原则
(1)首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句,如果有匹配的,则调到catch的地方进行处理。
(2)若没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。
(3)如果到达min函数的函数栈,依旧没有匹配成功,则终止程序。上述这个沿着调用链查找匹配的catch子句的过程称为栈展开,所以实际中我们最后都要加一个catch(...)捕获任意类型的异常,否则当有异常没有捕获,程序就会之间终止。
(4)找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
(5)若一直到main函数中都没有找到对异常的处理,则会将异常交给操作系统处理,而操作系统会直接终止程序的运行。
2.异常的重新抛出
有可能单个catch不能完全处理一个异常,在进行一些校正处理后,希望再交给更外层的调用链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。
异常的重新抛出:throw;
直接throw不跟任何内容,就是将捕获的异常重新抛出。

3.异常安全
(1)构造函数负责完成对象的构造和初始化,所以最好不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化。
(2)虚构函数负责完成对资源的清理,所以最好不要在析构函数中抛出异常,否则可能导致资源泄漏。
(3)C++中,异常经常会导致资源泄漏问题,比如在new和delete中抛出了异常,导致内存泄漏;在lock和unlock之间抛出了异常,导致死锁。C++中经常使用RAII来解决以上问题。
4.异常规范
(1)异常规范说明的目的是为了让函数的使用者知道该函数可能抛出的异常有那些。可以通过在函数的后面接throw(类型),列出该函数可能抛出的所有异常类型。
(2) 函数的后面接throw(),表示该函数不抛出异常。
(3)若无异常接口声明,则此函数可以抛出任何类型的异常。
注意:VS2019下忽略了异常规范


三、自定义异常体系
如果一个项目中,大家随意抛异常,那么外层调用者基本就没办法处理了,所以实际中都会定义一套继承的规范异常体系进行异常管理,这样大家抛出的都是继承的派生类对象,捕获基类对象即可。
四、C++标准库的异常体系
C++标准库提供了一系列标准的异常,我们可以在程序中使用这些标准的异常,它们是以父子类层次结构组织起来的:

每个异常的说明:

五、异常的优缺点
1.异常的优点
(1)异常对象定义好后,相比于错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包含堆栈调用信息,可以帮助我们更好的定位程序的错误原因。
(2)返回错误码的传统方式存在一个较大的问题:在函数调用链中,深层的函数返回了错误,那么得层层返回错误,最外层才能拿到错误。
(3)很多的第三库都包含异常,比如boost、gtest、gmock等等,那么我们在使用它们时就需要使用异常。
(4)很多测试框架都使用异常,这样能更好的使用单元测试等,进行白盒测试。
(5)部分函数使用异常更好处理,比如:T& operator这样的函数,如果pos越界了只能使用异常或终止程序处理,没办法通过返回值表示错误。
2.异常的缺点
(1)异常会导致程序的执行流混乱,并且运行时抛出异常就会乱跳,导致我们跟踪调试、分析程序时,比较困难。
(2)异常会有一些性能的开销,当然这个开销很小,在现代硬件条件下可以或略不计。
(3)C++没有垃圾回收机制,资源需要自己进行管理。而异常非常容易导致资源泄漏、死锁等异常安全问题。这需要使用RAII来处理资源管理问题。
(4)C++标准库的异常体系定义并不完美,导致大家各自定义各自的异常体系,非常混乱。
(5)异常使用不规范,随意抛异常,会导致外层捕获非常麻烦。所以异常规范主要有两点:①抛出异常的类型都继承自一个基类;②函数是否抛异常,抛出什么异常,都要使用func()throw()的方式进行规范化。但有的编译器又会忽略异常规范,比如VS2019,对于不知情者,可能造成较大困惑。
总结:虽然异常处理比较麻烦,但是总体而言还是利大于弊的。
相关文章:
C++程序设计——异常
一、C异常概念 异常处理是一种处理错误的方式,当一个函数发现自己无法处理的错误时,就可以抛出异常,让函数的直接或间接的调用者处理这个错误。 (1)throw:当问题出现时,程序会通过throw关键字抛…...
2022年第十三届蓝桥杯web开发—东奥大抽奖【题目、附官方解答】
冬奥大抽奖 介绍 蓝桥云课庆冬奥需要举行一次抽奖活动,我们一起做一个页面提供给云课冬奥抽奖活动使用。 准备 开始答题前,需要先打开本题的项目代码文件夹,目录结构如下: ├── css │ └── style.css ├── effect.g…...
一份两年前一个月的工作经历没写在简历上,背调前主动坦白,却被背调公司亮了红灯,到手的offer没了!...
只因为简历上漏写了一份一个月的工作,就被亮了背调红灯,这公平吗?一位网友就被狠狠坑了一把,来看下他的遭遇:他有一份两年前、时长一个月的工作经历没写在简历上,背调前主动和背调公司还有招聘方hr都说了这…...
C++游戏分析与破解方法介绍
1、C游戏简介 目前手机游戏直接用C开发的已经不多,使用C开发的多是早期的基于cocos2dx的游戏,因此我们这里就以cocos2d-x为例讲解C游戏的分析与破解方法。 Cocos2d-x是一个移动端游戏开发框架,可以使用C或者lua进行开发,也可以混…...
食堂总是拥挤不堪?解决用餐拥挤,教你一招
随着近几年科技的快速发展,行业里出现了很多新的名词,比如智慧社区、智慧旅游、智慧建筑,那么智慧食堂是什么呢?它又是如何实现全自助、全智能消费? 在先进的智能技术以及市场需求带动下,智慧食堂经历了由传…...
ubuntu系统安装时 MBR和GPT的区别
主引导记录(Master Boot Record , MBR)是指一个存储设备的开头 512 字节。它包含操作系统的引导器和存储设备的分区表。 全局唯一标识分区表(GUID Partition Table,缩写:GPT)是一个实体硬盘…...
我在windows10下,使用msys64 mingw64终端
系列文章目录 文章目录系列文章目录前言一、MSYS2是什么?前言 msys2官网 MSYS2 (Minimal SYStem 2) 是一个MSYS的独立改写版本,主要用于 shell 命令行开发环境。 同时它也是一个在Cygwin (POSIX 兼容性层)…...
个人2023FALL CS申请总结(PhD/MPhil/保研夏令营)
个人2023FALL CS申请总结(PhD/MPhil/保研夏令营)写在最前个人BG及申请情况个人BG申请情况MPhilPhD收获一句话总结:心态爆炸没用,脸皮够厚够勇就行 写在最前 真是一场恶战。有几天,我每天早上都海投几封套瓷邮件&…...
【优化算法】使用遗传算法优化MLP神经网络参数(TensorFlow2)
文章目录任务查看当前的准确率情况使用遗传算法进行优化完整代码任务 使用启发式优化算法遗传算法对多层感知机中中间层神经个数进行优化,以提高模型的准确率。 待优化的模型: 基于TensorFlow2实现的Mnist手写数字识别多层感知机MLP # MLP手写数字识别…...
CAM类激活映射 |神经网络可视化 | 热力图
文章目录前言:安装库:分类案例--ResNet50分割案例AttributeError: ‘tuple‘ object has no attribute ‘cpu‘RuntimeError: grad can be implicitly created only for scalar outputsTypeError: cant convert cuda:0 device type tensor to numpy. Use…...
RecyclerView+BaseRecyclerViewAdapterHelper显示不全只显示第一行item的解决问题
RecyclerViewBaseRecyclerViewAdapterHelper显示不全只显示第一行item,我懵了…,我不说多,直接说吧 先看一下适配器代码中的convert()方法: class MineRadioAdapter(layoutResId: Int R.layout.item_my_live) :BaseQuickAdapte…...
解决后端无法对前端的ajax请求重定向
本章目录: 问题描述 AJAX请求后端直接重定向失败解决方案 后端拦截请为响应头添加重定向标志后端拦截器为响应头添加重定向路径前端响应拦截器获取响应头数据,并通过location.href url 完成页面跳转一、问题描述 本来想在拦截器里设置未登录用户访问指…...
【Python】1分钟就能制作精美的框架图?太棒啦
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、准备二、基本使用与例子1.初始化与导出2.节点类型3.集群块4.自定义线的颜色与属性总结前言 Diagrams 是一个基于Python绘制云系统架构的模块,它能…...
淘宝必备的补单技巧及注意事项!
补单,是优化善后的s单。单只是模拟用户的购物习惯,而补单同时还要模拟整个店铺的综合数据,包括点击率、转化率等等,补到略高于同行、竞品的平均数据时,淘宝会判断为买家比较喜欢你的商品,从而给你更多推荐机…...
【实用篇】SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud分布式
文章目录一、服务拆分1.1 服务拆分Demo1.2 微服务远程调用二、Eureka2.1 Eureka原理2.2 Eureka-server服务搭建2.3 eureka-client服务注册2.4 eureka-client服务复制2.5 eureka服务发现三、Ribbon负载均衡3.1 负载均衡原理3.2 负载均衡策略3.3 自定义负载均衡策略3.4 饥饿加载与…...
私人飞机、公务机包机会成为富豪圈的主流出行方式吗?
从炫耀性消费到按需使用,私人飞机的消费群体正在被拓宽,但离“成为主流”还有一段距离。“时间就是金钱”为有钱人消费私人飞机提供合理动机,而这群高净值人群的数量增长则成为撑起市场基本面。据相关数据显示,2018年全球超级富豪…...
Oracle组织架构
组织架构 (一)业务组(BG) (二)法律实体(LE) (三)业务实体(OU) (四)库存组织(INV) …...
最小公倍数
目录 最小公倍数 程序设计 程序分析 最小公倍数 【问题描述】给定两个正整数,计算这两个数的最小公倍数。 【输入形式】输入包含多组测试数据,每组只有一行,包括两个不大于1000的正整数. 【输出形式】 对于每个测试用例,给出这两个数的最小公倍数,每个实例输出一行。…...
二叉树的后序遍历(力扣145)
目录 题目描述: 解法一:递归法 解法二:迭代法 解法三:Morris遍历 二叉树的后序遍历 题目描述: 给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。 示例 1: 输入:root …...
《Effective C++》读书纪实 -- 诸君同享
文章目录《Effective C》是一本经典的C编程指南,共包含50条C编程的最佳实践。 确定你的构造函数的行为 在构造函数中,应该尽可能地避免调用虚函数、非静态成员函数和虚基类的函数。 尽量使用const、enum、inline替换#define 使用const、enum、inline可以…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...
