一、简介
noexcept是一个C++11引入的关键字,用于表示一个函数或表达式在执行期间是否会抛出异常。
1.作用:
作为标识符时,在函数后面声明一个函数是否会抛出异常
作为函数时,检查一个函数是否会抛出异常
2.特点
提高代码效率:如果一个函数使用了noexcept声明,编译器会认为这个函数不会抛出异常,从而达到一些优化的目的,包括避免额外的堆栈操作和异常处理代码等原始代码以外的外围处理代码,这里包括,错误位置,错误原因,调用顺序,层级路径等,从而提高效率。
帮助程序员调试:如果一个函数没有使用noexcept声明,并且在函数内部抛出了异常,这个异常会在函数的调用栈上一路向上传递直到被捕获,如果捕获不到,程序就会崩溃。但如果使用了noexcept声明,在函数内部发生异常时,程序会直接调用std::terminate()函数终止程序,可以帮助快速发现和调试程序中的异常问题。
帮助编写高质量代码:可以明确表示函数是否会抛出异常,从而让函数的调用者更清楚更正确的处理异常情况
3.写法
noexcept、noexcept(true)、noexcept(false)、noexcept(expression)
noexcept表示noexcept(true),表示不会抛出异常
noexcept(false)表示可能会抛出异常
4.使用场景
用于表示函数不会抛出异常,提高代码的效率和可读性
用于表示函数可能会抛出异常,从而提醒函数的调用者需要正确的处理异常情况
用于重载抛出异常和不抛出异常两种版本的函数,便于调用者根据情况调用需要的版本
用于编写RALL类时,保证在析构函数中不会抛出异常,否则可能导致资源无法正常释放
用于使用move移动语义时,保证移动构造函数和移动赋值函数不会抛出异常
用于在使用标准库中算法和容器时,保证一些函数不会抛出异常
二、代码案例
重载不抛出异常和抛出异常两个版本函数
void func(x) noexcept(true)
{
cout<<x<<endl;
}
void func() noexcept(false)
{
throw1;
}
检查函数是否有声明noexcept函数
void func(x) noexcept(true)
{
cout<<x<<endl;
}
cout << boolalpha << noexcept(func(x)) << endl;
//boolalpha表示打印时,true打印单词"true",而不是打印数字"1"
设置函数是否抛出异常的条件
void swap(Type& x, Type& y) noexcept(noexcept(x.swap(y))) //C++11
{// 其它代码
x.swap(y);// 其它代码
}
表示x.swap(y)不发生异常,那该函数就不会发生异常
但是noecept关键字会影响接口的灵活性,例如,某个基类的某个虚函数设置为noexcept,派生类重写虚函数时也必须加上,否则可能会导致整个程序在发生异常时被终止
如果函数声明了noexcept同时调用了第三方库的函数,就需要处理第三方库所有可能出现的异常,将其封装处理,增加了代码工作量
noexcept的适用范围
移动构造函数
移动分配函数
析构函数
叶子函数:指的是不分配栈空间也不调用其它函数,也不存储非易失性寄存器,也不处理异常,因为函数调用就是一层一层往下,一个函数可以调用多个函数,就像树枝分叉,到了最末端就是叶子函数