解析C++中的 noexcept

一. 概述

noexcept 是C++11中的特性,既是一个说明符,也是一个运算符。能够说明函数是否会抛出异常,如下:

1 struct X {
 2 
 3     int f() const noexcept {
 4         return 58;
 5     }
 6 
 7     void g() noexcept {}
 8 };
 9 
10 int foo() noexcept {
11     return 42;
12 }

noexcept指示上述的几个函数不会抛出异常,编译器可以优化代码。

如果有异常抛出,则会调用std::terminate结束生命周期。

二. 带参数的noexcept

带参数的noexcept作用为:如果noexcept(true),则不会抛出异常,反之则可能有异常,下面的例子中,可以用noexcept检查传入模板参数是不是基础类型。

1 template <class T>
2 T copy(const T& o) noexcept(std::is_fundamental<T>::value) {
3     ...
4 }

这个函数可以优化为:

1 template <class T>
2 T copy(const T& o) noexcept(noexcept (T(o))) {
3     
4 }

这里用了2个noexcept,第二个判断T(o)是否可能抛出异常,第一个接受第二个的返回值,决定T类型复制函数是否声明为不抛出异常

三. noexcept使用场景

  1. 解决移动构造和移动赋值的问题

下例用noexcept实现一个移动语义的容器经常用到的工具函数swap。如果move没有抛出异常的可能,那么函数进行移动操作,否则进行复制操作。

1 template <class T>
2 void swap(T &a, T &b)
3 noexcept(noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b)))) {
4     static_assert (noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b))) );
5     T temp(std::move(a));
6     a = std::move(b);
7     b = std::move(temp);
8 }
  1. 用于析构函数。在新版本的编译器中,析构函数是默认加上关键字noexcept的。

  2. 叶子函数。叶子函数是指在函数内部不分配栈空间,也不调用其它函数,也不存储非易失性寄存器,也不处理异常。

四. 注意事项

  1. 在新版本编译器中,默认构造函数,默认复制构造函数,默认赋值函数,默认移动构造函数,默认移动赋值函数均自带noexcept,但使用者自定义或重载的上述函数需要手动加上noexcept才有此功能。

  2. c++11中保留了throw(), 实现和noexcept类似的功能,区别是throw()不会针对编译器进行优化,但是C++20中移除了throw()。

原文链接: https://www.cnblogs.com/Asp1rant/p/15505532.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/214655

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午2:25
下一篇 2023年2月13日 上午2:26

相关推荐