8-异常与错误

8-异常与错误

  • 1、简介
  • 2、异常处理
    • 2.1 抛出异常
    • 2.2 捕获异常
    • 2.3 匹配顺序
  • 3、异常说明
  • 4、构造函数中的异常
  • 5、析构函数中的异常
  • 6、标准库异常

1、简介

在程序编码过程中难免会出现错误,主要有:语法错误、逻辑错误、功能错误等,当我们面对以上错误时处理主要针对在实际运行环境中发生,却在设
计、编码和测试阶段无法预料的,当面对异常时,有三种典型的处理机制:

  • 通过返回值返回错误信息
    • 所有局部对象都能正确地被析构
    • 逐层判断,流程繁琐
  • 借助setjmp,/longjmp远程跳转(不建议使用,这种效率最高,但是如果使用不当,会造成更加严重的后果)
    • 一步到位,流程简单
    • 某些局部对象可能因此丧失被析构的机会
  • 抛出—捕获异常对象(c++推荐使用)
    • 形式上一步到位,流程简单
    • 实际上逐层析构局部对象,避免内存泄漏

2、异常处理

2.1 抛出异常

语法:throw 异常对象

  • 可以抛出基本类型的对象,如:
void foo(){FILE * txt = fopen("./a.txt", "r");if (!txt){cout << "文件打开失败" << endl;throw - 1;}cout << "文件打开成功" << endl;
}
  • 可以抛出类类型的对象
void bar(){FILE * txt = fopen("./a.txt", "r");if (!txt){cout << "文件打开失败" << endl;throw A(3);//以匿名临时对象抛出的异常,编译器会做优化,减少一次拷贝}cout << "文件打开成功" << endl;
}
  • 不可以抛出局部对象的指针
void fu(){FILE * txt = fopen("./a.txt", "r");if (!txt){cout << "文件打开失败" << endl;A a = A(3);// 构造Athrow &a; // 这里会进行一次拷贝}cout << "文件打开成功" << endl;
}

解释:这是因为在c++中所有的异常都是抛向C++标准库中的,在标准库中会保存一份异常抛出对象的副本,而在异常抛出之后,原抛出异常的地方会进行销毁处理。

2.2 捕获异常

语法:try{}catch(…)

  • 建议是在catch子句中使用引用接收异常对象,避免因拷贝构造带来的性能损失。
    int main(){try{C08_01();}catch (C08_B& b){// 这里就不会进行拷贝了,直接使用的是标准库里的对象cout << "捕获到异常B" << endl;b.info();}catch (C08_C& c){cout << "捕获到异常C" << endl;c.info();}catch (int & e){cout << e << endl;}catch (C08_A a){// 这里会进行一次拷贝a.info();}cout << "程序执行成功" << endl;return 0;
    }
    
- 推荐使用匿名临时对象的形式抛出异常
```c++
void bar(){FILE * txt = fopen("./a.txt", "r");if (!txt){cout << "文件打开失败" << endl;throw A(3);//以匿名临时对象抛出的异常,编译器会做优化,减少一次拷贝}cout << "文件打开成功" << endl;
}
  • 异常对象必须允许被拷贝构造和析构
    在这里插入图片描述

2.3 匹配顺序

根据异常对象的类型自上而下的顺序匹配,而不是最优匹配,因此对子类类型异常的捕获不要放在基类类型异常的捕获后面。
在这里插入图片描述

3、异常说明

异常说明是函数原型的一部分,旨在说明函数可能抛出的异常类型。

  • 语法格式:
	返回类型 函数名(参数列表) throw(异常类型1,异常类型2,...){函数体}
  • 异常说明是一种承诺,承诺函数不会抛出异常说明以外的异常类型。
    • 如果函数抛出了异常说明以外的异常类型,那么该异常将无法捕获,会导致进程中止
      在这里插入图片描述

    • std::unexpected()->std::terminate()->abort

    • 隐式抛出异常的函数也可以列出它的异常说明
      在这里插入图片描述

    • 异常说明可以没有也可以为空
      注意:
      1:没有异常说明时,表示可能抛出任何类型的异常,比如void foo(){};代表foo这个函数可能抛出任何类型的异常
      2:异常说明为空时,表示不会抛出任何类型的异常,比如void foo()throw(){}

    • 异常说明在函数的声明和定义中必须保持严格一致,否则将导致编译错误
      在这里插入图片描述

      • 忽略异常,不做处理
        在这里插入图片描述

4、构造函数中的异常

  • 构造函数可以抛出异常,某些时候还必须抛出异常
    • 构造过程中可能遇到各种错误,比如内存分配失败
    • 构造函数没有返回值,无法通过返回值通知调用者
  • 构造函数抛出异常,对象将被不完整构造,而一个被不完整构造的对象,其析构函数永远不会被执行
    • 所有对象形式的成员变量,在抛出异常的瞬间,都能得到正确地析构(构造函数的回滚机制)
    • 所有动态分配的资源,必须在抛出异常之前,自己手动释放,否则将形成资源的泄漏。
class C08_AA{public:C08_AA(){ cout << "AA类构造函数" << endl; }~C08_AA(){ cout << "AA类的析构函数" << endl; }
};
class C08_CC{
private:C08_AA aa;FILE *A;
public:C08_CC(){cout << "CC类构造函数" << endl;A = fopen("./a.txt", "r");if (!A){// 对于动态申请的资源,必须自己手动释放throw - 1;// 在构造函数中出现异常,那么所有对象形式的成员变量,在抛出异常的瞬间,都能得到正确地析构(构造函数的回滚机制)}	}~C08_CC(){cout << "CC类析构函数" << endl;}
};int main(){try{C08_CC cc;// 如果cc是完整函数对象,则会调用cc的析构函数,如果cc是残缺对象,则不会调用cc的析构函数}catch(...){// 捕获任意异常}C08_CC cc;return 0;
}

5、析构函数中的异常

不要在析构函数中主动抛出异常

  • 析构函数只会在两种情况下被系统调用:
    1:正常的销毁对象:当对象离开作用域或者显式的使用delete
    2:异常的销毁对象:在异常传递的堆栈辗转开解过程中销毁对象
  • 需要注意的是,对于第二种情况,此时系统中存在异常,而此时的析构函数中又抛出了异常,这时C++将通过std::terminate()函数,令进程中止
    所以为了避免出现这种情况,在析构函数中,对于可能引发异常的操作,尽量在析构函数内部处理掉,不要主动抛出异常。
class C08_D{
public:~C08_D(){throw "析构函数抛出的异常";	}
};
int main(){try{C08_D d;oneThrow();// 这里已经抛出了异常}// 此时d中析构函数中也抛出了异常,此时这个异常就捕获不到,然后就会被系统杀死catch (const char* a){cout << a << endl;}catch (...){}
}

6、标准库异常

在这里插入图片描述

  • exception:抽象类
  • runtime_error: 抽象类
  • logic_error:抽象类
  • overflow_error:上溢异常,一般用于容器满了的情况下
  • underflow_error:下溢异常,一般用于容器空了的情况下
  • invalid_argument:无效参数,一般用于实参和形参之间的数据不匹配
  • length_error:长度错误
  • out_of_range:超出范围
  • bad_alloc:new操作符申请失败,会抛出这个异常
  • bad_cast:动态类型转换中引用的转换失败,会抛出这个异常
  • bad_type_id:使用typeid操作符获取信息失败时,会抛出这个异常

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

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

相关文章

密闭空间作业应如何做好安全防护?

在现代工业与日常工作中&#xff0c;密闭空间作业已逐渐成为许多行业不可或缺的一部分。然而&#xff0c;这些看似寻常的空间却隐藏着诸多不为人知的风险。从窒息性气体到易燃易爆物质&#xff0c;从物理性危险到心理压力&#xff0c;每一项都足以威胁到作业人员的生命安全。因…

Llama模型家族之RLAIF 基于 AI 反馈的强化学习(六) RLAIF 代码实战

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

主键UUID和数据库自增ID怎么选择?

一、前言 最近在建表选择主键的时候有些纠结&#xff0c;我们经常使用的主键有两种UUID和自增ID&#xff0c;不知道选哪一种好。之前一直没有总结过这两种主键的区别&#xff0c;于是今天去总结了一下这两种主键的区别、优缺点&#xff0c;以便为我们以后主键选择提供一些参考。…

字符串匹配算法(三)Trie树算法

文章目录 Trie树的简介Trie树定义Trie树的实现 代码实现 Trie树的简介 Trie树定义 Trid树&#xff0c;也叫”字典树“。它是一个树形结构。专门处理字符串匹配的数据结构&#xff0c;用来解决字符串集中快速查找某个字符串的问题。 Trie 树的本质&#xff0c;就是利用字符串之…

LeetCode503:下一个更大元素Ⅱ

题目描述 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&#xff0c;这…

记录一次云服务器无法连接的排查过程

运行环境&#xff1a;阿里云服务器 故障外显原因&#xff1a;登录失败,操作系统禁用了密码登录方式 控制台监控数据显示云盘读写BPS拉满了 因为之前问过线上售后&#xff0c;让安装了atop监控&#xff0c;&#xff0c;所以先打开atop日志&#xff1a; atop -r /var/log/atop…

自动驾驶中的长尾问题

自动驾驶中的长尾问题 定义 长尾问题&#xff08;Long-Tail Problem&#xff09;是指在数据分布中&#xff0c;大部分的数据集中在少数类别上&#xff0c;而剩下的大多数类别却只有少量的数据。这种数据分布不平衡的现象在许多实际应用中广泛存在&#xff0c;特别是在自动驾驶…

音视频开发—H265相关概念和压缩原理详解(GOP、宏块、帧内压缩、帧间压缩)

文章目录 1.什么是GOP&#xff1f;1.1 GOP介绍1.2.GOP中I帧/B帧/P帧1.3.I帧和IDR的区别联系I帧&#xff08;Intra Frame&#xff09;IDR帧&#xff08;Instantaneous Decoding Refresh Frame&#xff09;区别总结 1.4 帧与分组的关系1.5 SPS与PPSSPS&#xff08;Sequence Param…

【前端视野下的数据库概念探秘】——信息化人员必备知识面试宝典:解码“视图”与“游标”

【前端视野下的数据库概念探秘】——信息化人员必备知识&面试宝典&#xff1a;解码“视图”与“游标” 视图&#xff1a;数据的魔法透镜基本概念前端为何关心&#xff1f;代码示例&#xff1a;案例一功能使用思路 游标&#xff1a;数据流的指针基础认知前端视角代码示例&am…

竹纤维家装元宇宙:虚拟空间与绿色生活的融合

在全球化和科技迅速发展的今天&#xff0c;元宇宙作为一种全新的互联网应用和社会形态&#xff0c;正逐步渗透到人们生活的各个方面。特别是在家装行业&#xff0c;竹纤维作为一种新型环保材料&#xff0c;结合元宇宙的概念&#xff0c;正在引领一场绿色生活的革命。 ### 一、…

6.5 Go 指针

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

beamer修改超链接颜色报错

beamer修改超链接颜色报错 使用 \usepackage[colorlinkstrue, urlcolorblue]{hyperref} % 只将超链接设置为蓝色设置 url颜色时、会报错 这是因为在使用 LaTeX 的 Beamer 类创建演示文稿时&#xff0c; Beamer 自身已经自动加载了 hyperref 宏包&#xff0c;并对其进行了一些…

EasyExcel之动态表头导出不生效

今天接到一个优化需求&#xff0c;表格导出后的表头顺序和页面不一致&#xff0c;要优化成一致的。根据传入的字段&#xff0c;动态导出数据&#xff0c;并保证顺序。 我看到导出的实体类都有ExcelProperty注解&#xff0c;同时也在官网查看了这注解的含义和使用。 ExcelPrope…

如何在Linux系统中搭建Zookeeper集群

一、概述 ZooKeeper是一个开源的且支持分布式部署的应用程序&#xff0c;是Google的Chubby一个开源的实现&#xff1b;它为分布式应用提供了一致性服务支持&#xff0c;包括&#xff1a;配置维护、域名服务、分布式同步、组服务等。 官网&#xff1a;https://zookeeper.apach…

3D轻量化的三大应用解决方案

老子云平台https://www.laozicloud.com/ 为不同应用场景提供了三大解决方案。 01 单模型轻量化解决方案 数字化时代&#xff0c;越来越多的C2M定制、文旅、电商等行业&#xff0c;为了开拓市场&#xff0c;提升企业竞争力&#xff0c;开始把目光投向产品的3D展示交互。 单模…

ADuM1201可使用π121U31间接替换π122U31直接替换

ADuM1201可使用π121U31间接替换π122U31直接替换 一般低速隔离通信150Kbps电路可使用π121U31&#xff0c;价格优势较大。速度快的有其它型号可达10M,200M,600M。 本文主要介绍ADUM1201,替换芯片π121U31简单资料请访问下行链接 只要0.74元的双通道数字隔离器&#xff0c;1T1…

一个程序员的牢狱生涯(48)男人

星期一 男人 无论发生了什么事,看守所的一切都在按部就班的进行着,墙上的电视在晚上七点钟的时候准时打开,到了所有的号子集体收看“新闻联播”的时间。 号子里除了小x州站在厕所门口没有动外,其他人都安静地做回自己的位置,同样是坐班的姿势,只不过不用‘自我反省’,不…

【字典树(前缀树) 哈希映射 后序序列化】1948. 删除系统中的重复文件夹

本文涉及知识点 字典树&#xff08;前缀树) 哈希映射 后序序列化 LeetCode 1948. 删除系统中的重复文件夹 由于一个漏洞&#xff0c;文件系统中存在许多重复文件夹。给你一个二维数组 paths&#xff0c;其中 paths[i] 是一个表示文件系统中第 i 个文件夹的绝对路径的数组。 …

xmake+xrepo自建仓库添加交叉编译工具链

xmakexrepo自建仓库添加交叉编译工具链 最近想将交叉编译工具链放到xrepo自建仓库中&#xff0c;在xmake中引用&#xff0c;方便多个电脑快速实现交叉编译。 xmake官方文档感觉不够详细&#xff0c;折腾了好久&#xff0c;这里做个记录。 基本步骤如下&#xff1a; 添加自建…

13.优化界面化的游戏辅助

12.使用mfc实现游戏辅助的界面 在它的代码上进行修改 12.使用mfc实现游戏辅助的界面它的代码是频繁读写游戏的内存&#xff0c;这样不是很好&#xff0c;下面的代码是在它的基础上进行了封装&#xff0c;控制无敌的逻辑在我们申请的内存中实现&#xff08;也就是在一个全局中实…