C++笔记——第十六篇 异常

news2024/11/16 16:25:43

 

目录

1.C语言传统的处理错误的方式

2. C++异常概念

3. 异常的使用

3.1 异常的抛出和捕获

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

3.2异常安全

4.异常的优缺点



1.C语言传统的处理错误的方式



传统的错误处理机制:
1. 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。
2. 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误
3. C 标准库中setjmp和longjmp组合。这个不是很常用
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。



2. C++异常概念




异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。
throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
catch: 想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多个catch进行捕获。
try: try 块中的代码标识即将被激活的特定异常,它后面通常跟着一个或多个 catch 块。

如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。

try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码

try
{
        // 保护的标识代码
}catch( ExceptionName e1 )
{
        // catch 块
}catch( ExceptionName e2 )
{
        // catch 块
}catch( ExceptionName eN )
{
        // catch 块
}

 



3. 异常的使用




3.1 异常的抛出和捕获



异常的抛出和匹配原则
1. 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
2. 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的传值返回)
4. catch(...)可以捕获任意类型的异常,问题是不知道异常错误是什么。

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

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


1. 首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。如果有匹配的,则调到catch的地方进行处理。
2. 没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。
3. 如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的catch子句的过程称为栈展开。所以实际中我们最后都要加一个catch(...)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
4. 找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。


3.2异常安全


构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化
析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等)
C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和unlock之间抛出了异常导致死锁,C++经常使用RAII来解决以上问题。



4.异常的优缺点




C++异常的优点:



1. 异常对象定义好了,相比错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包含堆栈调用的信息,这样可以帮助更好的定位程序的bug。
2. 返回错误码的传统方式有个很大的问题就是,在函数调用链中,深层的函数返回了错误,那么我们得层层返回错误,最外层才能拿到错误

3. 很多的第三方库都包含异常,比如boost、gtest、gmock等等常用的库,那么我们使用它们也需要使用异常。
4. 很多测试框架都使用异常,这样能更好的使用单元测试等进行白盒的测试。
5. 部分函数使用异常更好处理,比如构造函数没有返回值,不方便使用错误码方式处理。

比如T&operator这样的函数,如果pos越界了只能使用异常或者终止程序处理,没办法通过返回值表示错误

 


C++异常的缺点


1. 异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。这会导致我们跟踪调试时以及分析程序时,比较困难。
2. 异常会有一些性能的开销。当然在现代硬件速度很快的情况下,这个影响基本忽略不计。
3. C++没有垃圾回收机制,资源需要自己管理。有了异常非常容易导致内存泄漏、死锁等异常安全问题。这个需要使用RAII来处理资源的管理问题。
4. C++标准库的异常体系定义得不好,导致大家各自定义各自的异常体系,非常的混乱。
5. 异常尽量规范使用,否则后果不堪设想,随意抛异常,外层捕获的用户苦不堪言。所以异常规范有两点:

一、抛出异常类型都继承自一个基类。

二、函数是否抛异常、抛什么异常,都使用 func()throw();的方式规范化


 

 

 

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

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

相关文章

飞腾ft2000-麒麟V10-SP1安装Docker、运行gitlab容器

目录 一、安装及配置docker 1、卸载docker相关包及删除相关配置文件 2、安装二进制docker 1.下载软件包 2.解压 3.修改镜像加速地址 4.修改profile文件 5.启动docker 6.docker常用命令 二、安装并启动gitlab镜像 1.安装gitlab镜像 1.查询满足使用需求的gitlab版本 2…

很佩服的一个Google大佬,离职了。。

这两天,科技圈又有一个突发的爆款新闻相信不少同学都已经看到了。 那就是75岁的计算机科学家Geoffrey Hinton从谷歌离职了,从而引起了科技界的广泛关注和讨论。 而Hinton自己也证实了这一消息。 提到Geoffrey Hinton这个名字,对于一些了解过…

使用 Mercury 直接从 Jupyter 构建 Web 程序

动动发财的小手,点个赞吧! 有效的沟通在所有数据驱动的项目中都至关重要。数据专业人员通常需要将他们的发现和见解传达给利益相关者,包括业务领导、技术团队和其他数据科学家。 虽然传达数据见解的传统方法(如 PowerPoint 演示文…

Oracle SQL优化相关数据项

要掌握SQL调优技术,就需要能读懂SQL语句的执行计划,要想读懂SQL语句的执行计划,不仅需要准确理解SQL语句执行计划中各操作及其含义,还需要准确理解SQL语句执行计划中各数据项的含义。本书第7章中,已经对SQL语句执行计划中各个操作的含义做了详尽的阐述,本章中,我们将对S…

爱普特APT32F110x系列时钟介绍

最近要用APT32F110x做一些开发,顺便学习一下。 APT32F110x 是由爱普特推出的基于平头哥(T-Head Microsystems)CPU 内核开发的 32 位高性能低成本单片机。 APT32F1104x基于嵌入式 Flash 工艺制造,内部丰富的模拟资源,包…

ShardingJDBC核心概念与快速实战

目录 ShardingSphere介绍 ShardingSphere特点 ShardingSphere简述 ShardingSphere产品区分 ShardingJDBC实战 核心概念 实战 ShardingJDBC的分片算法 ShardingSphere目前提供了一共五种分片策略: 分库分表带来的问题 ShardingSphere介绍 ShardingSphere特…

结合SSE实现实时位置展示与轨迹展示

概述 实时位置与实时轨迹的展示是webgis中非常常见的一个功能,本文结合SSE来实现实现此功能。 SSE简介 SSE是Sever-Sent Event的首字母缩写,它是基于HTTP协议的,在服务器和客户端之间打开一个单向通道,服务端响应的不再是一次性…

车牌输入框 封装 (小程序 vue)

车牌输入框 封装 小程序licenseNumber.jslicenseNumber.jsonlicenseNumber.wxmllicenseNumber.wxss样例 vuevnp-input-box.vuevnp-input.vuevnp-keyboard.vue样例 小程序 licenseNumber.js const INPUT_NUM 8;//车牌号输入框个数 const EmptyArray new Array(INPUT_NUM).fi…

6个「会议议程」实例和免费模板

我们都参加过一些团队会议,在这些会议上,大多数与会者对会议的目的一无所知,而发言者则使讨论偏离轨道。 接下来就是一场真正的灾难了。 你会发现你的团队因为“上述会议”而浪费了很多时间,却没有达到任何目的。 好消息! 一个…

【Python】序列类型②-元组

文章目录 1.元组简介2.元组的定义2.1定义只有一个元素的元组 3.元组的下标访问4.元组的常用方法5.使用in判断是否存在元素6.多元赋值操作 1.元组简介 元组和列表一样可以存放多个,不同数据类型的元素 与列表最大的不同就是:列表是可变的,而元组不可变 2.元组的定义 元组的定义:…

TCP/UDP协议

一、协议的概念 什么是协议? 从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。 假设,A、B双方欲传输文件。规定: 第一次,传输文件名,接收方接收到文件名,…

Springboot +Flowable,ReceiveTask的简单使用方法

一.简介 ReceiveTask(接受任务),它的图标如下图所示: ReceiveTask 可以算是 Flowable 中最简单的一种任务,当该任务到达的时候,它不做任何逻辑,而是被动地等待用户确认。 ReceiveTask 往往适…

RepVGG: Making VGG-style ConvNets Great Again

文章地址:《RepVGG: Making VGG-style ConvNets Great Again》 代码地址:https://github.com/megvii-model/RepVGG 文章发表于CVPR2021,文章提出一种将训练态和推断态网络结构解耦的方法。文章认为目前复杂的网络结构能够获取更高的精度&am…

学大数据需要java学到什么程度

大数据需求越来越多,只有技术在手不愁找不到工作。 学习大数据需要掌握什么语言基础? 1、Java基础 大数据框架90%以上都是使用Java开发语言,所以如果要学习大数据技术,首先要掌握Java基础语法以及JavaEE方向的相关知识。 2、My…

记一次OJ在线代码编辑器(代码编译+运行,C、C++、Java)

如何在SpringBootVue的项目中实现在线代码编译及执行(支持编译运行C、C、Java),研究了一天,真实能用,下面直接上源码!!! ————————————————————————————…

MySQL 知识:迁移数据目录到其他路径

一、系统环境 操作系统:Centos 7 已安装环境:MySQL 8.0.26 二、开始操作 2.1 关闭SELinux 为了提高 Linux 系统的安全性,在 Linux 上通常会使用 SELinux 或 AppArmor 实现强制访问控制(Mandatory Access Control MAC&#xff…

中间件的概念

中间件(middleware)是基础软件的一大类,属于可复用的软件范畴。中间件在操作系统软件,网络和数据库之上,应用软件之下,总的作用是为处于自己上层的应用软件提供运行于开发的环境,帮助用户灵活、高效的开发和集成复杂的…

阶段二38_面向对象高级_网络编程[UDP单播组播广播代码实现]

知识: InetAddresss:getByName,getHostName,getHostAddress方法UDP通信程序:单播,组播,广播代码实现一.InetAddress 的使用 1.static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称&#x…

【Java】通过反射方法不改变HashCode以修改String的值

如何修改String的值? 我们首先会想到如下两种方法 方式一:通过StringBuild/StringBuffer String s1 "Hello World!"; System.out.println("s1"s1" HashCode"s1.hashCode()); StringBuilder sb new StringBuilder(s1…

Android JNI配置CMakeLists.txt修改.cpp在logcat打印日志

Android JNI配置CMakeLists.txt修改.cpp在logcat打印日志 C/C代码里面常用的printf没法在Android 的logcat输出显示。需要特别配置C才能显示在logcat里面。 (1)CMakeLists.txt定义: find_library( # Sets the name of the path variable.l…