异常安全与Noexcept——编写永不失败的代码

简介: 在C++中,“不抛出异常”是一个比“正确”更严格的要求。一个函数可以是正确的(在任何有效输入下都能完成其任务),但仍然可能抛出异常。

在C++中,“不抛出异常”是一个比“正确”更严格的要求。一个函数可以是正确的(在任何有效输入下都能完成其任务),但仍然可能抛出异常。而一个标记为noexcept的函数,则承诺了更强的保证:无论发生什么,这个函数都不会抛出异常。这种承诺对于构建健壮的系统至关重要,特别是在析构函数、移动操作、swap函数以及某些关键路径上。
参考:https://vrhyh.cn/category/yinshi.html

noexcept关键字在C++11中被引入,取代了C++98中不常用的throw()规范。与throw()不同,noexcept不要求编译器检查函数是否真的抛出了异常——违反noexcept承诺的行为是未定义行为,通常会导致程序终止。这种设计反映了C++社区的务实态度:与其试图捕获和处理意外异常,不如直接终止程序,因为继续执行可能导致更严重的数据损坏。

什么情况下应该使用noexcept?最佳实践是只在确实不会抛出异常的函数上使用noexcept。这些函数包括:析构函数(它们应该总是noexcept)、移动构造函数和移动赋值运算符(如果可能的话)、swap函数、简单的getter和setter、以及任何只进行算术运算或指针操作而不分配内存的函数。标记一个会抛出异常的函数为noexcept是一个严重的错误,因为当异常被抛出时,程序会立即终止,而不是通过正常的异常处理流程。

noexcept不仅仅是文档性质的——它对代码生成和标准库的行为有实际影响。标准库通过std::is_nothrow_move_constructible等类型特征来检查类型的noexcept属性。一个经典的例子是std::vector的重新分配:当vector需要增长时,它需要将旧元素移动到新内存。如果移动构造函数是noexcept的,vector会使用移动操作,这通常很快;如果移动构造函数可能抛出异常,vector会回退到拷贝操作,以保证强异常安全(即在分配失败时保持原vector不变)。这意味着一个遗漏的noexcept可能导致严重的性能退化。
参考:https://vrhyh.cn/category/zhongyi.html

noexcept对异常安全级别有直接影响。C++定义了三个异常安全级别:基本保证(基本保证:操作后对象处于有效状态,无资源泄漏)、强保证(操作要么成功要么无变化)和不抛出保证(操作永不失败)。noexcept函数提供了最强的不抛出保证,这种保证对于某些操作是必需的——例如,在析构函数中抛出异常是致命的,因为析构函数在栈展开过程中被调用时,如果再抛出异常,程序会立即终止。

编写不抛出异常的代码需要特定的技巧。一个常见的方法是预先分配:在执行任何可能失败的操作之前,先完成所有可能抛出异常的工作。例如,在实现一个noexcept的赋值运算符时,你可以先构造一个临时副本(这一步可能抛异常),然后与当前对象交换(交换操作应该是noexcept的),最后让临时副本销毁。通过这种“拷贝-交换”惯用法,你可以将抛出异常的风险集中到可以处理的地方,而关键的交换和销毁操作则是安全的。
参考:https://vrhyh.cn/category/zhongyi.html

另一个技巧是使用非抛出版本的库函数。标准库中的许多函数都有不抛出的版本,例如std::copy和std::move在某些条件下可以不抛出。但要注意,这不总是保证的——如果迭代器的拷贝或赋值可能抛异常,那么算法本身也可能抛异常。类似地,算术操作通常不抛异常,但整数溢出在C++中是未定义行为而不是异常,所以你不会从中得到异常安全的保证。

noexcept与RAII的交互尤为重要。考虑一个数据库连接类,其析构函数需要关闭连接。如果关闭连接时网络错误,我们无法抛出异常(因为析构函数中的异常很危险),也无法忽略错误(因为用户可能想知道关闭失败)。一个常见的解决方案是提供一个单独的close函数,用户可以显式调用来处理错误,而析构函数在close失败时要么静默忽略(不推荐),要么记录日志(更合理),要么断言(用于调试)。这种设计将异常安全的负担转移到调用者身上,同时保持了析构函数的noexcept保证。

C++17引入了noexcept作为类型系统的一部分。一个函数指针的类型现在可以包括noexcept信息,这意味着void (f1)() noexcept和void (f2)()是不同的类型。这种变化提高了类型安全性——你不能将一个可能抛异常的函数赋值给一个要求noexcept的函数指针。但这也带来了兼容性问题:许多现有代码假定所有函数指针都是可以抛异常的,升级到C++17后可能需要修改类型声明。

在实际工程中,是否对所有可能标记为noexcept的函数都标记noexcept?答案是否定的。过度使用noexcept可能会导致不必要的代码重复,或者迫使开发者做出不切实际的承诺。更务实的策略是:析构函数、swap函数、移动操作等关键路径应该总是noexcept(除非有充分的理由不这样做);其他函数如果实现简单且不分配资源,也可以标记noexcept;但对于可能失败的操作(如文件IO、网络通信、内存分配),则不应该标记noexcept。
参考:https://vrhyh.cn

目录
相关文章
|
存储 数据采集 机器学习/深度学习
主数据管理的前世 今生 未来(一文深入了解主数据管理)(下)
根据Gartner的定义,“主数据管理(MDM)是一种技术支持的规程,业务和IT部门共同工作,以确保企业共享主数据资产的唯一性、准确性、语义一致性和可靠性……”
主数据管理的前世 今生 未来(一文深入了解主数据管理)(下)
|
6月前
|
存储 缓存 搜索推荐
昇腾RecSDK Torch整体方案介绍
RecSDK是基于昇腾平台的搜索推荐广告框架,支持Atlas系列硬件,兼容TensorFlow/PyTorch,提供高效模型训练。具备动态特征管理、多级缓存、算子优化、流水线并行等核心能力,实现计算与存储协同加速,助力大规模推荐系统高效开发与部署。(238字)
昇腾RecSDK Torch整体方案介绍
|
缓存 前端开发 数据可视化
前端基础(七)_表单的基本组成与使用
本文详细介绍了HTML表单的基本组成和使用,包括`<form>`标签、`<input>`表单域、`<select>`下拉列表、`<textarea>`多行文本域等元素。文章解释了表单的提交方式(GET和POST)、表单域的各种类型(文本、密码、单选按钮、复选框等)、提交按钮和重置按钮的作用,以及如何通过`<label>`标签提高表单的可访问性。此外,还讨论了表单元素的属性,如`readonly`、`disabled`、`maxlength`等。
470 1
|
监控 安全 Java
现代 Java 技术开发宠物管理系统实操案例解析
本文通过一个宠物管理系统项目,深入讲解Java中的封装、继承和多态特性。系统基于Java 8+开发,结合Stream API与Lambda表达式,展示现代Java技术的实际应用。封装部分使用Record类简化数据模型,继承设计通过抽象类与接口实现代码复用,多态则通过统一接口处理不同宠物行为。案例涵盖模板方法模式、策略模式等设计思想,并提供最佳实践建议,解决常见问题如继承滥用和类型转换异常。资源地址:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
380 0
|
人工智能 搜索推荐 大数据
大家都在怎么用AI?2024趋势报告
大家都在怎么用AI?2024趋势报告
|
程序员
什么是后门
后门( Back Door )是指一种绕过安全性控制而获取对程序或系统访问权的方法。在软件的开发阶段,程序员常会在软件内创建后门以便可以修改程序中的缺陷。如果后门被其他人知道,或是在发布软件之前没有删除,那么它就成了安全隐患。
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
787 3
|
人工智能 算法 搜索推荐
云端问道11期方案教学-创建专属AI助手-阿里云百炼产品能力分享
阿里云百炼产品能力分享旨在帮助用户深入了解百炼的核心功能,并快速将大模型与系统结合。主要内容包括:1. 百炼的产品定位和能力简介,涵盖模型推理、应用搭建等;2. 知识检索RAG智能体的应用能力和优势,介绍其高效构建知识库的步骤及常见问题;3. 最佳落地案例实践,如宠物行业AI助手和产业分析类互联网企业的Copilot机器人。通过这些内容,用户可以全面掌握百炼在实际业务中的应用方法和效果。
645 0
|
芯片 SoC
深入理解AMBA总线(零)绪论
深入理解AMBA总线(零)绪论
937 0
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
2137 3

热门文章

最新文章