noexcept 关键字

2024-02-26 23:36
文章标签 关键字 noexcept

本文主要是介绍noexcept 关键字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

noexcept 的基本语法

noexcept 是
C++11 为了替代 throw() 而提出的一个新的关键字,在
C++ 中使用函数异常声明列表来查看函数可能抛出的异常。比如:

void func() throw (int,double);

上例就是一个函数异常声明列表,该声明指出 func 可能抛出int和 double 类型的异常。但是在实际编程中很少使用这种写法,所以这一特性在 C++11 中被抛弃。另外,如果异常声明列表写成如下形式:

void func() throw();

这种写法表示函数 func 不抛出任何异常,而这种写法在 c++11 中被新的关键字 noexcept 异常声明所取代。

语法上 noexcept 修饰符有两种形式,一种就是简单地在函数声明后加上 noexcept 关键字。比如:

void func() noecept;

另外一种形式则是接受一个常量表达式(参阅《常量表达式》)作为参数,如下所示:

void func() noexcept(常量表达式);

常量表达式的结果会被转换成一个 bool 类型的值,该值为 true,表示函数不会抛出异常,反之则可能抛出异常。而不带常量表达式的 noexcept
相当于声明了 noexcept(true),即不会抛出异常。

noexcept 的使用

noexcept 可以用来阻止异常的传播和扩散,请看下面的例子:

#include

using namespace
std;

void Throw(){throw
1;}

void NoBlockThrow()
{ Throw(); }

void BlockThrow()
noexcept{ Throw(); }

int main(){

try {

Throw();

}

catch(…) {

cout << “Found throw.”
<< endl; // Found throw

}

try {

NoBlockThrow();

}

catch(…) {

cout << “Throw is not
blocked” <<endl;

}

try {

BlockThrow();

}

catch(…) {

cout << “Found throw
1” << endl;

}

}

在上面的例子中,我们定义了 Throw 函数,该函数的唯一作用是抛出一个异常。而 NoBlackThrow 则是一个 noexcept 修饰的函数。

接着,我们再来看一下上面示例的输出结果:

Found throw.

Throw is not
blocked

terminate called
after throwing an instance of ‘int’

然后我们分析运行结果可以得到这样的结论:NoBlockThrow
会让Throw 函数抛出的异常继续抛出,直到 mian 中的
catch 语句将其捕捉。而 BlockThrow 则会直接调用 std::terminate 中断程序的执行从而阻止了异常的继续传播。

注解:std::terminate 用来强制终止进程

而当
noexcept 作用于模板时,则增强了 c++ 的泛型编程的能力。例如:

template

void fun() noexcept(noexcept(T()))
{}

上面的模板函数会根据条件实现 noexcept 的修饰版本或者无 noexcept 修饰的版本。fun 函数是否是一个 noexcept 的函数,将由 T() 表达式是否会抛出异常所决定,当第二个 noexcept 参数是一个有可能抛出异常的表达式的时候,其返回值为 false ,这时就实现了无 noexcept 修饰的版本,反之,则是实现了 noexcept 修饰的版本。

noexcept 析构函数中的应用

noexcept 更大的用处就是保证程序的安全。因此出于安全考虑,C++11 标准中类的析构函数默认为 noexcept(true)。但是,如果程序员显式地为析构函数指定了
noexcept(false) 或者类的基类或成员有 noexcept(false) 的析构函数,析构函数就不会再保持默认值。

请看下面具体的例子:

#include

using namespace
std;

class People {

public:

~People() { throw 1;} // warning: throw
will always call terminate()

};

class Student {

public:

~Student() noexcept(false) {throw 2;}

};

class Singer {

public:

Student St;

};

int funP() { People
p; }

int funSt() {
Student st; }

int funSi() {
Singer si; }

int main(){

try{

funSt();

}

catch(…){

cout << “caught funSt.”
<< endl;

}

try {

funSi();

}

catch(…) {

cout << “caught funSi.”
<< endl;

}

try {

funP();

}

catch(…){

cout << “caught funP”
<< endl;

}

}

输出结果:

caught funSt.

caught funSi.

terminate called
after throwing an instance of 'int’­

在上面的例子中,无论使析构函数声明为 noexcept(false) 的类 Student 还是包含了 Student 类型成员的类 Singer,它们的析构函数都是可以抛出异常的。只有什么都没有声明的类­­­­­­­ People 的析构函数默认为 noexcept(true),因此阻止了异常的扩散。

这篇关于noexcept 关键字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

c# checked和unchecked关键字的使用

《c#checked和unchecked关键字的使用》C#中的checked关键字用于启用整数运算的溢出检查,可以捕获并抛出System.OverflowException异常,而unchecked... 目录在 C# 中,checked 关键字用于启用整数运算的溢出检查。默认情况下,C# 的整数运算不会自

Oracle Start With关键字

Oracle Start With关键字 前言 旨在记录一些Oracle使用中遇到的各种各样的问题. 同时希望能帮到和我遇到同样问题的人. Start With (树查询) 问题描述: 在数据库中, 有一种比较常见得 设计模式, 层级结构 设计模式, 具体到 Oracle table中, 字段特点如下: ID, DSC, PID; 三个字段, 分别表示 当前标识的 ID(主键), DSC 当

关键字synchronized、volatile的比较

关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字的执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。多线程访问volatile不会发生阻塞,而synchronize

JavaScript 根据关键字匹配数组项

要在JavaScript数组中根据关键字匹配项,可以使用filter方法结合一个测试函数。以下是一个示例代码,定义了一个函数findByKeyword,该函数接受一个数组和一个关键字,然后返回一个新数组,其中包含与关键字匹配的所有项。 function findByKeyword(array, keyword) {return array.filter(item => {// 假设要匹配的是对象

MySQL 的关键字

MySQL 中的关键字是数据库中具有特殊含义的保留字,它们用于定义数据库结构、操作数据库数据和控制数据库行为。关键字在 MySQL 查询中扮演着至关重要的角色,因为它们是 SQL 语句的核心组成部分。 1. 数据定义语言 (DDL) 关键字 数据定义语言 (DDL) 关键字用于定义、修改和删除数据库结构,如数据库、表和索引等。这些关键字通常用于创建、删除表结构以及修改表的列等操作。 1.1

C++中的mutable关键字详解

目录 1.概述 2.使用场景 3.示例 4.mutable修饰Lambda表达式 5.注意事项 1.概述         在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。         我们知道,被const关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以

[Python]生成器和yield关键字

生成器和yield关键字 1.生成器介绍: 概述: ​ 它指的是 generator, 类似于以前学过的: 列表推导式, 集合推导式, 字典推导式… 作用: ​ 降低资源消耗, 快速(批量)生成数据. 实现方式: ​ 1.推导式写法. my_generator = (i for i in range(5)) ​ 2.yield写法. def get_generator():for i

java基础总结11-面向对象7(super关键字)

在JAVA类中使用super来引用父类的成分,用this来引用当前对象,如果一个类从另外一个类继承,我们new这个子类的实例对象的时候,这个子类对象里面会有一个父类对象。怎么去引用里面的父类对象呢?使用super来引用,this指的是当前对象的引用,super是当前对象里面的父对象的引用。 1 super关键字测试 package cn.galc.test;/*** 父类* @autho

java基础总结08-面向对象4(static关键字)

原来一个类里面的成员变量,每new一个对象,这个对象就有一份自己的成员变量,因为这些成员变量都不是静态成员变量。对于static成员变量来说,这个成员变量只有一份,而且这一份是这个类所有的对象共享。 静态成员变量与非静态成员变量的区别 以下面的例子为例说明 package cn.galc.test;public class Cat {/*** 静态成员变量*/private static