【C++笔记】异常处理

news2025/1/17 1:06:48

C语言处理错误的方式

传统的错误处理机制: 1.终止程序缺陷:用户难以接受。 2.返回错误码:缺陷:需要自己去查错误码对应的解释。 C语言一般使用错误码来处理错误,部分情况下才会用终止情况处理处理严重的错误。

C++异常

异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数直接或者间接的调用处理这个问题。  1.throw:当问题出现时,程序会抛出异常。通过关键字throw完成。  2.catch:在处理异常问题的地方,通过异常处理程序捕获异常。catch关键字可用于捕获异常,可以有多个catch捕获异常。  3.try:try块中的代码表示将被激活的特定异常,它后面会使用一个或者多个catch块。 如果一个块炮捶个异常,捕获方法会使用try和catch。try中防止可能抛出的异常代码,try块的代码被称为保护代码。 语法规则:

 try
 {
     //保护的标识代码
 }
 //catch块
 catch(e1)
 {
 //...
 }
 //catch可以有多个

异常的使用

异常抛出和捕获

异常的抛出和匹配原则

1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活catch的哪个处理代码。 2.被选中的处理代码是调用链中的与该对象类型匹配并且抛出异常位置最近的的哪一个。 3.抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的对象可能是一个临时对象,所以会出现一个拷贝对象,这个拷贝的临时对象会在被catch后销毁(处理类似于函数的传值返回)。 4.catch{...}可以捕获任意类型的异常 5.实际中抛出和捕获异常的匹配原则有个例外,并不是什么类型都完全匹配,可以抛出派生类对象,使用基类捕捉。

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

1.首先检查throw本身是否在try块的内部,如果是再查找匹配的catch‘语句。如果有匹配的,则调到catch的地方进行处理。 2.没有匹配的catch则退出当前栈,继续在调用函数的栈中查找匹配的catch。 3.如果daodamain函数的栈,依旧没有匹配的,就终止程序(沿着调用链查找匹配的catch子句的过程称为栈展开) 4.找到匹配的catch语句并处理后,会沿着catch字句后面继续执行。

代码展示:

 #include<iostream>
 using namespace std;
 double Div(double a, double b)
 {
     if (b == 0)//抛异常
     {
         throw "除数不能为0";
     }
     return b / a;
 }
 void Func()
 {
     int a, b;
     cin >> a>>b;
     cout << Div(a, b) << endl;
 }
 int main()
 {
     try {
         Func();
     }
     catch (const char* err)
     {
         cout << err << endl;
     }
     catch (...)
     {
         cout << "未知错误" << endl;
     }
     return 0;
 }
 //打印:除数不能为0

异常的重新输入

可能单个的catch不能完全处理一个异常,再进行一些矫正处理以后,希望再交给更外层的调用链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。 示例:

 
#include<iostream>
 using namespace std;
 double Div(double a, double b)
 {
     if (b == 0)//抛异常
     {
         throw "除数不能为0";
     }
     return b / a;
 }
 void Func()
 {
     int* arr = new int[10];
     //当出现除0错误的时候,arr就没有处理。
     //这里波或异常后,不直接处理异常,而是抛出去,让外部链函数处理
     try {
         int a, b;
         cin >> a >> b;
         cout << Div(a, b) << endl;
     }
     catch (...)
     {
         cout << "delete[]" << arr << endl;
         delete[] arr;//有异常,释放arr防止内存泄漏
         throw;//重新抛出,没加啥参数,是因为不知道是啥异常,反正抛出就对了
     }
     //....
     cout << "delete[]" << arr << endl;
     delete[] arr;
 }
 int main()
 {
     try {
         Func();
     }
     catch (const char* err)
     {
         cout << err << endl;
     }
     catch (...)
     {
         cout << "未知错误" << endl;
     }
     return 0;
 }
 ​

异常安全

构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不完整或者没有完全初始化。 析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏的风险。 C++经常会导致内存泄漏的问题,智能指针能有效解决此类问题。

异常规范

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

 // 这里表示这个函数会抛出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;

C++标准库的异常体系

 

exception 类的直接派生类:

异常名称说 明
logic_error逻辑错误。
runtime_error运行时错误。
bad_alloc使用 new 或 new[ ] 分配内存失败时抛出的异常。
bad_typeid使用 typeid 操作一个 NULL [指针],而且该指针是带有虚函数的类,这时抛出 bad_typeid 异常。
bad_cast使用 dynamic_cast 转换失败时抛出的异常。
ios_base::failureio 过程中出现的异常。
bad_exception这是个特殊的异常,如果函数的异常列表里声明了 bad_exception 异常,当函数内部抛出了异常列表中没有的异常时,如果调用的 unexpected() 函数中抛出了异常,不论什么类型,都会被替换为 bad_exception 类型。

logic_error 的派生类:

异常名称说 明
length_error试图生成一个超出该类型最大长度的对象时抛出该异常,例如 vector 的 resize 操作。
domain_error参数的值域错误,主要用在数学函数中,例如使用一个负值调用只能操作非负数的函数。
out_of_range超出有效范围。
invalid_argument参数不合适。在标准库中,当利用string对象构造 bitset 时,而 string 中的字符不是 0 或1 的时候,抛出该异常。

runtime_error 的派生类:

异常名称说 明
range_error计算结果超出了有意义的值域范围。
overflow_error算术计算上溢。
underflow_error算术计算下溢。

对expection类实现自己的异常类

int main()
 {
  try{
  vector<int> v(10, 5);
  // 这里如果系统内存不够也会抛异常
  v.reserve(1000000000);
  // 这里越界会抛异常
  v.at(10) = 100; 
  }
  catch (const exception& e) // 这里捕获父类对象就可以
  {
  cout << e.what() << endl;
  }
  catch (...)
  {
  cout << "Unkown Exception" << endl;
  }
  return 0; }

异常的优缺点

优点

1.异类对象定义好了,相比错误码的方式可以准确清晰的站输出各种错误的信息,甚至是包含战队的信息,这样可以更好的定位程序的bug 2.返回错误码的传统方式有个巨大的问题,在函数调用链中,深层的函数返回了错误,那么我们得层层返回错误,最外层才能拿到错误。 3.很多第三方库包含异常。 4.不分寒暑使用异常更好处理,不方便使用错误码的情况。

缺点

1.异常会导致程序的执行流乱跳,比较混乱。并且运行时出错抛异常就会乱跳,这使得调试分析时比较困难。 2.异常会有一些性能的开销。 3.C++没有垃圾回收机制,资源需要自己管理。 4.C++标准库的异常体系一般,导致自定义对象的各自的一场体系,非常的混乱。 5.异常尽量规范使。

总结:异常是利大于弊。

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

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

相关文章

初识Liunx下的进程状态和环境变量以及进程优先级

文章目录前言1.进程状态1.阻塞与挂起2.Linux下的进程状态1.概念知识2.R状态2.休眠状态(S/D&#xff09;3.T状态4.Z状态(僵尸进程)和X状态5.孤儿进程3.环境变量1.概念2.获取环境变量1.环境变量表2.函数获取环境变量3.关于环境变量的理解和main函数中的两个参数1.环境变量的理解2…

学习笔记--目标检测基础知识大全

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 目录 1.特点 2.数据集 2.1 VOCS数据集 2.2 COCO数据集 3.评价指标 3.1 GroundTruth 3.2 IOU(交并比&#xff0c;Intersection over Union) 3.3 基本指标 3.4 AP与mAp 3.5 案例演示 4. 脑图&#xff…

代码规范----编程规约(下)

目录 四、OOP规约 五、日期时间 六、集合处理 四、OOP规约 &#xff08;1&#xff09;、避免通过一个类的对象引用访问此类的静态变量或静态方法&#xff0c;无谓增加编译器解析成本&#xff0c;直接用类名来访问即可 &#xff08;2&#xff09;、所有的覆写方法&#xff0…

【C语言学习笔记】:二级指针

指针可以指向一个普通类型的数据&#xff0c;例如 int、double、char 等&#xff0c;也可以指向一个指针类型的数据&#xff0c;例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针&#xff0c;我们就称它为二级指针&#xff0c;或者指向指针的指针。 假设…

Leetcode.2017 网格游戏

题目链接 Leetcode.2017 网格游戏 Rating &#xff1a; 1719 题目描述 给你一个下标从 0 开始的二维数组 grid&#xff0c;数组大小为 2 x n&#xff0c;其中 grid[r][c]表示矩阵中 (r, c)位置上的点数。现在有两个机器人正在矩阵上参与一场游戏。 两个机器人初始位置都是 (0…

带你看懂RuoYi动态数据源切换

文章目录数据源是什么一、spring中是如何处理各种数据源的&#xff1f;1.开搞springboot2.创建一个测试类二、有了如上的理论,那么想想动态切换数据源吧参考若依的动态数据源配置总结数据源是什么 数据源,对于java来说,就是可用的数据库,那么我平时开发的springboot springclo…

算机网络安全基础知识5:sql注入漏洞攻击,DVWA演示sql注入漏洞,如何利用sql注入查看数据库信息,sqlmap,sql注入漏洞的防御

算机网络安全基础知识5:sql注入漏洞攻击&#xff0c;DVWA演示sql注入漏洞&#xff0c;如何利用sql注入查看数据库信息&#xff0c;sqlmap&#xff0c;sql注入漏洞的防御 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能…

Unity/C#------委托与事件(一篇文章彻底搞懂...)

一&#xff1a;委托 所有的代码语言创造者母语都是英语&#xff0c;我们从英语翻译到中文的过程中难免会存在一些不太能还原本意的词&#xff0c;比如我之前一直不理解构造函数和析构函数&#xff0c;只知道这俩货作用相反&#xff0c;直到我看到了它的英文意思&#xff0c;Con…

spring重点整理篇--springMVC(嘿嘿,开心哟)

Spring MVC是的基于JavaWeb的MVC框架&#xff0c;是Spring框架中的一个组成部分(WEB模块) MVC设计模式&#xff1a; Controller&#xff08;控制器&#xff09; Model&#xff08;模型&#xff09; View&#xff08;视图&#xff09; 重点来了&#x1f604; SpringMVC的工作机制…

Nginx+Tomcat实现负载均衡、动静分离(脚本方法)

一、Nginx 负载均衡实现原理1、Nginx 实现负载均衡是通过反向代理实现反向代理&#xff08;Reverse Proxy&#xff09; 是指以 代理服务器&#xff08;例&#xff1a;Nginx&#xff09; 来接受 internet 上的连接请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0…

【PGMAN:无监督的生成式多对抗网络】

PGMAN: An Unsupervised Generative Multiadversarial Network for Pansharpening &#xff08;PGMAN&#xff1a;一种无监督的生成式多对抗网络&#xff09; 全色锐化的目的是融合低分辨率多光谱&#xff08;MS&#xff09;图像和由卫星获取的高分辨率全色&#xff08;PAN&a…

OnlyOffice验证(三)OnlyOffice编译结果自制Docker镜像

OnlyOffice验证&#xff08;三&#xff09;OnlyOffice编译结果自制Docker镜像 之前验证了OnlyOffice验证&#xff08;二&#xff09;在Centos7上部署OnlyOffice编译结果&#xff0c;由于现在普遍都是容器化部署&#xff0c;所以还是验证下Doker镜像打包是否可行&#xff0c;因为…

渗透five86-2

kali的ip为192.168.56.104&#xff0c;利用nmap或arp-scan -l查看发现了靶机ip192.168.56.120这里存在20、21、80端口&#xff0c;这边需要将靶机ip进行域名绑定&#xff0c;对/etc/hosts改写&#xff0c;将192.168.56.120 与five86-2绑定输入ip后&#xff0c;发现了有log in由…

Kubernetes的网络架构及其安全风险

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/129137821 一、常见的Kubernetes网络架构 如图所示&#xff1a; 说明&#xff1a; 1、集群由多个节点组成。 2、每个节点上运行若干个Pod。 3、每个节点上会创建一个CNI网桥&#xff08;默认设备名称…

Qt——自定义界面之QStyle

1. Qt控件结构简介 首先我们要来讲讲GUI控件结构&#xff0c;这里以QComboBox为例&#xff1a; 一个完整的控件由一种或多种GUI元素构成&#xff1a; Complex Control Element。Primitive Element。Control Element。 1.1 Complex Control Element Complex control elements …

【C语言跬步】——指针数组和数组指针(指针进阶)

一.指针数组和数组指针的区别 1.指针数组是数组&#xff0c;是一种存放指针的数组&#xff1b; 例如&#xff1a; int* arr[10]; 2.数组指针是指针&#xff0c;是一种指向数组的指针&#xff0c;存放的是数组的地址&#xff1b; 例如&#xff1a; int arr[5]; int (p)[5]&a…

Redis学习(二):Redis安装测试

概述 Redis是什么 Redis, Remote Dictionary Server, 即远程字典服务。免费开源的数据库。 由C语言编写&#xff0c;支持网络&#xff0c;可基于内存亦可持久化的日志型、KV数据库&#xff0c;并提供所种语言的API。 Redis能干嘛 用于内存存储&#xff0c;持久化。rdb、ao…

[学习笔记]黑马程序员Spark全套视频教程,4天spark3.2快速入门到精通,基于Python语言的spark教程

文章目录视频资料&#xff1a;一、Spark基础入门&#xff08;环境搭建、入门概念&#xff09;第二章&#xff1a;Spark环境搭建-Local2.1 课程服务器环境2.2 Local模式基本原理2.3 安装包下载2.4 Spark Local模式部署第三章&#xff1a;Spark环境搭建-StandAlone3.1 StandAlone…

驾考笔记_2023

科目一1> 扣分制度1.1> 超速1.2> 超载1.3> 车牌1.4> 速记口诀2> 满分学习2.1> 消分学习2.2> 满分重考&#xff1b;3> 罚款制度3.1> 考证3.2> 审验教育3.3> 其他4> 车速规定4.1> 高速_最低限速4.2> 普路_最高限速5> 证件相关5.…

双指针法|位运算|离散化|区间合并

目录 双指针算法 位运算 离散化 序列合并 双指针算法 题目描述&#xff1a;1.输入n个单词&#xff0c;每个单词在输入的时候按空格隔开&#xff0c;之后打印出每个单词且换行 #include<iostream> #include <string>using namespace std; int main() {strin…