C++ Primer 5th笔记(chap 18 大型程序工具)noexcept

2024-03-28 08:38

本文主要是介绍C++ Primer 5th笔记(chap 18 大型程序工具)noexcept,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 通过提供 noexcept 说明 ( noexcept specification ) 指定某个函数不会抛出异常。 其形式是关键字 noexcept 紧跟在函数的参数列表后面

{// 紧跟在函数的参数列表后面// 该说明应该在函数的尾置返回类型之前// 在成员函数中,noexcept说明符应该出现在const以及引用限定之后// 而在final,override,或者虚函数的=0之前。void recoup(int) noexcept;//不会抛出异常void alloc(int);//可能会抛出异常//noexcept要么出现在该函数的所有声明和定义语句中//要么一次也不出现。//我们也可以在函数指针的声明和定义中指定noexcept//在typedef或类型别名中不能出现noexcept
}

对于一个函数来说, noexcept 说明要么出现在该函数的所有声明语句和定义语句中, 要么一次也不出现。

  • 该说明应该在函数的尾置返回类型之前。

  • 也可以在函数指针的声明和定义中指定 noexcept。

  • 在 typedef 或类型别名中则不能出现 noexcept。

  • 在成员函数中, noexcept 说明符需要跟在 const 及引用限定符之后, 而在 final、 override 或虚函数的=0 之前

1.1 违反异常说明

编译器并不会在编译时检查noexcept说明。如果在一个函数中说明了noexcept的同时又含有throw语句,或者调用可能抛出异常的其他函数,编译器将会顺序编译通过,并不会因为这种违反异常说明滚的情况而报错。(又可能会有编译器会提出警告)

// 尽管该函教明显违反了异常说明, 但它仍然可以顺利编译通过
void f ( ) noexcept //承诺不会抛出异常
{throw exception ( ); / / 违反了异常说明
}

因此可能会出现一个函数既声明了不会抛出异常,而又抛出了异常。此时,一旦抛出异常,程序就会调用terminate以确保遵守不在运行时抛出异常的承诺。上述过程对是否执行栈展开没有约定。
因此noexcept用在两种情况。

  • 我们确认函数不会抛出异常
  • 我们根本不会处理该异常

1.2 异常说明的实参

noexcept 说明符接受一个可选的实参, 该实参必须能转换为 bool 类型: 如果实参是 true, 则函数不会抛出异常; 如果实参是 false, 则函数可能抛出异常:

void recoup (int) noexcept (true); / / recoup 不会抛出异常
void alloc (int ) noexcept ( false);/ / alloc 可能抛出异常

1.3 noexcept 运算符 (noexcept operator)

noexcept 运算符是一个一元运算符, 它的返回值是一个 bool 类型的右值常量表达式,用于表示给定的表达式是否会抛出异常
和sizeof一样,noexcept也不会对该表达式求值。

eg. noexcept (recoup (i) ) // 如果 recoup 不抛出异常则结果为 true; 否则结果为 falsenoexcept (e)
当 e 调用的所有函数都做了不抛出说明且 e 本身不含有 throw 语句时, 上述表达式为
true; 否贝lj noexcept (e> 返回 falsevoid f ( ) noexcept (noexcept (g ( > ) ); //f 和 g 的异常说明一致
如果函数 g 承诺了不会抛出异常, 则 f 也不会抛出异常; 如果 g 没有异常说明符, 或者 g
虽然有异常说明符但是允许抛出异常, 则 f 也可能抛出异常

1.4 异常说明与指针、 虚函数和拷贝控制

1.4.1 指针

函数指针及该指针所指的函数必须具有一致的异常说明。

  • 如果我们为某个指针做了不抛出异常的声明, 则该指针将只能指向不抛出异常的函数。
  • 如果我们显式或隐式地说明了指针可能抛出异常, 则该指针可以指向任何函数, 即使是承诺了不抛出
    异常的函数也可以
// recoup和pf1都承诺不会抛出异常
// alloc可能会抛出错误
void (*pf)(int) noexcept = recoup;
void (*pf2)(int) = recoup;//正确
pf = alloc;//错误,
pf2 = alloc;//正确

1.4.2 虚函数

如果一个虚函数承诺了它不会抛出异常,则它后续的派生类的虚函数也必须做出同样的承诺。
如果基类的虚函数允许抛出异常时,我们可以设置派生类对应的函数不能抛出异常,当然也可以是允许抛出异常

class Base {
public:virtual double f1(double) noexcept;// 显式和隐式地指出可能会抛出异常virtual int f2() noexcept(false);virtual void f3();
};class D : public Base {
public:double f1(double);//错误,没有指明是noexceptint f2() noexcept(true);//正确,虽然基类的是可能抛出异常的void f3() noexcept;//正确,同上
};

1.4.3 拷贝控制成员

  • 当编译器合成拷贝控制成员时,同时也生成一个异常说明符。
  • 如果对所有成员和基类的所有操作都承诺了不会抛出异常,则合成的成员是noexcept的。
  • 如果合成成员调用的任意一个函数可能会抛出异常,则合成的成员是noexcept(false)的。
    -我们定义了一个析构函数,但是没有为它提供异常说明,编译器将会合成一个,合成的异常说明符将与假设编译器为类合成的析构函数时所得的异常说明一致。

这篇关于C++ Primer 5th笔记(chap 18 大型程序工具)noexcept的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855069

相关文章

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

sqlite3 命令行工具使用指南

《sqlite3命令行工具使用指南》本文系统介绍sqlite3CLI的启动、数据库操作、元数据查询、数据导入导出及输出格式化命令,涵盖文件管理、备份恢复、性能统计等实用功能,并说明命令分类、SQL语... 目录一、启动与退出二、数据库与文件操作三、元数据查询四、数据操作与导入导出五、查询输出格式化六、实用功

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二