【C++基础】C++11的noexcept声明符 与 异常传播

本文介绍C++11中noexcept的用途与用法,包括noexcept声明符和运算符的具体应用,以及异常传播的概念与规则。同时探讨了noexcept如何帮助优化编译,并指出不当使用可能导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ noexcept:

1、用途

C++11使用noexcept指明函数是否抛出异常:

若函数不抛异常,则可做编译优化
即便函数抛异常,也不再说明所抛异常类型(简化)

注意,C++03将throw(ExceptionType)放到函数后面,说明函数会抛出什么类型的异常,也被称为“异常规约”
java用 throws关键字做同样的事情

2、用法

1、noexcept声明符的用法:

void foo() noexcept {}		//函数不抛异常

void foo() noexcept(true) {} // noexcept(true)等价于noexcept

void foo() {} // 可能会抛出异常

void foo() noexcept(false) {} // noexcept(false)等价于什么也不写,可能会抛出异常

需要注意的地方:
1、noexcept不能用于区分重载函数。
在这里插入图片描述
在这里插入图片描述

2、如果我们声明函数时说了它不抛异常,但是又在noexcept函数中抛出异常,这就等于调用std::terminate(),终结程序的运行。

void f() { /* 潜在抛出异常 */ }
void g() noexcept {
  f();      // 合法,即 使 f 抛出 
  throw 42; // 合法,等效于调用 std::terminate
}

在这里插入图片描述
编译时会报警告:
在这里插入图片描述
主函数调用foo(),运行时程序会终止:
在这里插入图片描述

2、noexcept运算符的用法

bool noexcept( expression )     

noexcept 运算符进行编译时检查,若表达式声明为不抛出任何异常则返回 true。
noexcept (may_throw())返回false,表明可能会抛异常。
noexcept (no_throw())返回true,表明不抛异常。

void may_throw();
void no_throw() noexcept;
int main() {
  std::cout << std::boolalpha
            << "Is may_throw() noexcept? "
            << noexcept (may_throw()) << '\n'
            << "Is no_throw() noexcept? "
            << noexcept (no_throw()) << '\n';
}

异常传播

1、异常传播的定义

嵌套的函数调用,每个函数中都有 try-catch 块,内层函数抛出异常,这时候会出现异常传播
在这里插入图片描述
如图,func3中出现了异常,如果没有被func2中的catch捕获到的话,异常会随着函数的返回,交给函数的上一级(func1)处理,如果func1也处理不了,则交给main函数处理,如果main函数处理不了,程序会崩溃。
需要注意的地方:

  1. try块中抛出异常的语句后面的语句
  2. catch的异常类型与所需匹配的异常实例的类型

2、异常传播中的规则

try-catch的执行规则

  1.  try块中的异常:抛异常的语句后的块代码都被跳过,并开始找exception handler的代码(即找catch代码)
    
  2.  找exception handler的流程:沿函数调用的链反向寻找
     (1)    按catch块的顺序对比,找到则执行catch块代码
     (2)    找不到,退出当前函数,将异常传给调用当前函数的函数
    

仍然以上图调用链为例:

Quiz: function3抛出

  1. Exception3,执行哪些statement?
    执行Process ex3 -> statement6-> statement3-> statement4-> statement1-> statement2;
  2. Exception2,执行哪些statement?
    执行Process ex2 ->statement4-> statement1-> statement2;
  3. Exception1,执行哪些statement?
    执行Process ex1 -> statement2;
  4. Exception0,执行哪些statement?
    返回到主函数,程序崩溃

3、异常传播的代价

C++引入的异常处理会为程序带来额外开销和代价。

(1)项目中使用异常,需要考虑与未使用异常的第三方和旧项目代码的整合问题,避免出现一异常安全问题;
(2)异常使用不当,容易造成内存泄漏和程序崩溃,比如函数内抛出异常需要注意栈展开导致的内存泄露,析构函数抛出异常将程序置于不确定状态等;
(3)异常的跳转会彻底扰乱程序的执行流程并难以判断,给代码调试和维护增加难度;
(4)为保证写出异常安全的代码,往往需要借用C++其它特性,如智能指针,这又进一步加剧了代码可读性的恶化与程序的时空开销,包括编译时间的延长,运行效率的较低以及代码尺寸的增大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾牙慧者

欢迎请作者喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值