为“异常”努力是值得的

异常是OO语言处理错误的方式,在C++中,鼓励使用异常。侯捷再书中谈起异常,“十年前撰写“未将异常考虑在内的”函数是为一种美好实践,而今我们致力于写出“异常安全码”。”可见异常安全的重要。

说起异常安全,首先就要是异常的出现是为弥补C语言缺陷。再者,将介绍异常的概念,异常安全的条件。

C语言处理错误的缺陷

  • 程序意外终止

                比如:内存申请错误,越界,除0错误,会直接终止程序

  • 错误码难以解读

                在出错后会返回一个数字(错误码)。此时会包含俩层含义:是错误信息?是结果?

                错误码需要程序员查找相关库信息

     出现错误直接终止程序是非常不允许的情况。

C++异常的引入

异常:当一个函数出现自己无法解决的错误时,可以抛出异常,让函数的直接或间接调用者处理这个问题。

处理异常的三个关键字:

throw:当问题出现时,要抛出异常,通过throw抛出

catch:用于捕获异常。可以有多个catch

try:try中的代码将被激活特定的异常,try后跟着一个或多个catch块。

try要和catch匹配使用。

catch块中的内容不一定会被执行,只有当异常抛出且被捕获时才会执行,否则不执行。

	try {//保护块}catch (ExceptionName e1){//}catch (ExceptionName e2){//}

异常的抛出与匹配规则

  • 异常是有抛出对象引发的,该对象类型决定调用哪个块的。比如:抛出int类型的异常,catch参数为int的来接收。实际上:抛出和捕获类型不一定要相同,这里可以抛出派生对象。


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


  • 异常抛出的对象后,会生成一个临时拷贝,传给catch

在实际运用中,抛异常抛出通常对象是一个类,包含错误信息和错误码。

由于私有成员在内外拿不到,故通过函数调用返回错误信息和错误码。

对于临时拷贝的类型是const 故函数要添加const,才可调用。


  • catch(...)可以捕获任意类型的对象。

抛出的异常在没有继承情况下,要匹配相应的类型才能被捕获,会在catch中一直匹配,直到catch(...)处理任意类型。但是无法得到抛出的异常对象。

异常的重新抛出

对于内存资源申请,抛异常要极为谨慎。
在上述的例子中,虽然有对内存资源释放,但是抛异常后捕捉异常跨越栈帧,导致内存没有被释放。内存的申请没有释放是一件很严重的事情。
在这里,希望能在main函数中,将内存释放。
我们必须将异常重新抛出,在Func函数中,捕获异常,再将异常重新抛出。

异常安全


具有异常安全的函数会

  • 不泄露任何资源。例如上述代码在抛出异常后,后续的delete不会被调用。
  • 不允许数据败坏。异常抛出后,异常被捕获,导致栈帧的跳跃,关键信息没有被执行。

解决资源泄露是比较轻松的

确保析构,智能指针。

这里我们专注解决数据败坏的问题。

在构造函数中,最好不要抛异常,可能会导致没有完全构造

析构过程最好不好抛异常

在lock和unlock抛异常会导致死锁

异常安全函数有以下三个保证

  • 基本承诺

        如果异常被抛出,程序内任何事物都保持在有效状态,没有任何对象和数据结构被破坏,所有对象处于一种内部前后一致的状态。

  • 强烈保证

        如果函数调用成功,就完全成功。如果函数失败,程序就恢复到调用之前状态。

  • 不抛掷保证

        承诺异常绝不抛出,因为它们总能够完成它们原先承诺的功能。

在C++11中,如果一个函数明确的不抛异常的话,就用noexcept

thread() noexcept;
thread (thread&& x) noexcept;

异常优点

  • 可以清晰展示错误信息
  • 抛异常可以直接拿到错误信息,不需要重重返回。
  • 第三方库的异常安全很规范
  • 部分函数更好检查。如构造函数没有返回值。

缺点

执行的跳跃,乱流。追踪程序困难。

C++没有垃圾回收机制,异常任意导致内存泄漏

标准库的异常不完善。

异常是被鼓励使用。时间不断前进,我们与时俱进!

参考:
<<Effective c++>>

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

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

相关文章

自定义GPTs的Actions 调用外部API测试 返回API的结果:成功

我的自定义GPT&#xff1a;https://chat.openai.com/g/g-sOqIFZgIy-superbrain 效果&#xff1a;chatGPT调用我的天气接口返回天气。 可以看见把json结果变成md格式(人方便阅读)了。与物理世界连接成功&#xff0c;太强大了。 我建的测试示例&#xff1a;https://3.wjsou.…

王炸升级!PartyRock 10分钟构建 AI 应用

前言 一年一度的亚马逊云科技的 re:Invent 可谓是全球云计算、科技圈的狂欢&#xff0c;每次都能带来一些最前沿的方向标&#xff0c;这次也不例外。在看完一些 keynote 和介绍之后&#xff0c;我也去亲自体验了一些最近发布的内容。其中让我感受最深刻的无疑是 PartyRock 了。…

物联网+AI智慧工地云平台源码(SaaS模式)

智慧工地云平台充分运用数字化技术&#xff0c;聚焦施工现场岗位一线&#xff0c;依托物联网、互联网、AI等技术&#xff0c;围绕施工现场管理的人、机、料、法、环五大维度&#xff0c;以及施工过程管理的进度、质量、安全三大体系为基础应用&#xff0c;实现全面高效的工程管…

spring IOC介绍

spring的Ioc真是个好东西啊&#xff0c;那它到底是什么东西呢&#xff0c;控制反转&#xff0c;到底是怎么转的呢&#xff1f; 假设啊你现在是一个导演&#xff0c;想排部戏&#xff0c;那是不是得需要演员和舞台(spring中的bean)&#xff0c;如果按平常的编程思维就是new 一个…

蓝牙物联网对接技术难点有哪些?

#物联网# 蓝牙物联网对接技术难点主要包括以下几个方面&#xff1a; 1、设备兼容性&#xff1a;蓝牙技术有多种版本和规格&#xff0c;如蓝牙4.0、蓝牙5.0等&#xff0c;不同版本之间的兼容性可能存在问题。同时&#xff0c;不同厂商生产的蓝牙设备也可能存在兼容性问题。 2、…

枚举类的final修饰

今天开发跟我反馈了一个很奇怪的问题&#xff0c;说有个对象的状态属性是枚举类&#xff0c;设置了该对象的状态后&#xff0c;插入数据库&#xff0c;这个状态没了&#xff0c;凭空消失了&#xff0c;变成了空白字符串。这让人感觉非常奇怪&#xff0c;整个问题排查后得到的结…

低代码平台选型标准:功能、应用与优劣势分析

在数字化转型的浪潮下&#xff0c;中小企业面临满足市场需求、提高效率和竞争力的挑战。低代码平台做为数字化转型的重要工具&#xff0c;为中小企业带来了快速开发和定制应用程序解决方案。但是&#xff0c;在很多低代码平台中&#xff0c;选择是一个重要的环节。企业应该根据…

docker---资源控制

docker的资源控制 对容器使用宿主机的资源进行限制。 三种控制方向&#xff1a;CPU 内存 磁盘I/O docker使用linux自带的功能cgroup&#xff1b;control groups是linux内核系统提供的一种可以限制记录&#xff0c;隔离进程所使用的物理资源机制。 docker借助此…

自定义TypeHandler 将mysql返回的逗号分隔的String转换到List

sql执行如下&#xff1a; 这里我定义的接受类&#xff1a; 但是这里报了错JSON parse error: Cannot deserialize value of type java.util.ArrayList<java.lang.String>from Object value (token JsonToken.START_OBJECT); nested exception is com.fasterxml.jackson…

通过静态HTTP实现负载均衡

在当今的互联网环境中&#xff0c;随着用户数量的不断增加和业务需求的不断扩大&#xff0c;单台服务器往往无法承受所有的访问压力。为了确保网站的可用性和性能&#xff0c;负载均衡成为了一种常见的解决方案。本文将探讨如何通过静态HTTP实现负载均衡&#xff0c;以提升网站…

AUTOSAR CP Port Driver简介

Port Driver 1 背景2 基于 EB 及 TC39X 配置3 Port API 使用1 背景 Port driver 在 AUTOSAR 中是一个比较冷门的模块,基本上在 MCAL 层级,关注的人也少,他由不像其他模块那样通用型比较强,Port 在每种内核的 MCU 的配置都有区别,甚至有些芯片直接没有 Port 模块,使用其他方…

磁盘的移臂调度方法

refer: 理解&#xff1a; 访问磁盘需要先找到数据&#xff0c;在机械硬盘里并不是直接电子读取&#xff0c;需要移动磁头到相应的数据块上才可以读取&#xff08;磁头移动到目标柱面&#xff0c;即磁道&#xff0c;然后磁片旋转磁头才能访问到相应扇区&#xff0c;进而读取数…