C++ 异常安全(一):盘点那些不应抛出异常的函数

根据 C++ 自身的机制,有些函数是不允许抛出异常的。这些函数通常具备关键的功能,如资源管理或底层的基础功能,需要确保在任何情况下都能稳定运行,不会因抛出异常而中断。

遵循相关原则是保证异常安全的重要基础,下面我们就来盘点一下不应抛出异常的函数:

1. 析构函数

析构函数负责清理对象占用的资源,如果析构函数在异常处理过程中被调用(例如在栈展开时),它抛出的新异常会与当前处理的异常冲突。

C++ 标准推荐析构函数不应抛出异常,从 C++11 开始,析构函数隐式地被声明为noexcept(true),除非另有指定。

2. 移动构造函数和移动赋值运算符

在 C++11 及以后的标准中,移动构造函数和移动赋值运算符不应抛出异常,这是因为移动操作通常比复制操作更快,且不会抛出异常,编译器可以利用这一点来优化代码,例如通过消除不必要的临时对象。

3. swap 函数

swap 函数用于交换两个对象的状态。如果 swap 函数抛出异常,那么可能会导致对象状态的不一致。

4. 资源回收函数

如 operator delete 等,这些函数负责内存释放,如果这些函数抛出异常,可能会导致内存泄露或程序崩溃。

5. 重载或特化不抛异常的标准函数

标准库中的一些函数不抛出异,如 hash::operator() 等,对这些函数的重载或特化也不应抛出异常,否则会使标准库无法正常工作,也会造成出乎意料的错误。

6. 特定上下文中的函数

在某些特定上下文中,如异常处理过程中(catch 块)或异常类自身的成员函数中,除非是有意重新抛出异常,否则也不应抛出异常,以保持程序的异常安全状态。

总之,在设计函数时,应仔细考虑是否应该抛出异常。更进一步地,可参见下列文章对每一点的详细说明:

  1. 全局对象的初始化过程不可抛出异常
  2. 析构函数不可抛出异常
  3. 内存回收函数不可抛出异常
  4. 对象交换过程不可抛出异常
  5. 移动构造函数和移动赋值运算符不可抛出异常
  6. 异常类的拷贝构造函数不可抛出异常
  7. 异常类的构造函数和异常信息相关的函数不应抛出异常
  8. 与标准库相关的 hash 过程不应抛出异常

更多编程注意事项请参见:《360 安全规则集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值