C++ -- noexcept关键字
noexcept关键字
作用:告诉编译器,函数中不会发生异常,有利于编译器对程序做出更多的优化,比如避免生成处理异常的额外代码,减少程序的大小
例子
声明了noexcept和没有声明的同一段代码:
safeDivide 当除数为0时,会直接调用std::terminate()来中止程序而不是throw错误
// use of use of the noexcept specifier
#include <iostream>
using namespace std;
// Function that may throw an exception
int divide(int a, int b)
{
if (b == 0) {
throw runtime_error("Error: Division by zero");
}
return a / b;
}
// Function that will not throw any exceptions (using
// noexcept)
double safeDivide(double a, double b) noexcept
{
if (b == 0) {
// In this case, std::terminate will be called if b
// is zero
cerr << "Error: Division by zero in safeDivide"
<< std::endl;
terminate();
}
return a / b;
}
int main()
{
cout << "noexcept value for divide(): "
<< noexcept(divide(10, 0)) << "\n";
cout << "noexcept value for safeDivide(): "
<< noexcept(safeDivide(10.0, 0.0));
return 0;
}
Output:
noexcept value for divide(): 0
noexcept value for safeDivide(): 1
有条件的noexcept:
// C++ code to demonstrate the use of the
// noexcept specifier with a function template
#include <bits/stdc++.h>
using namespace std;
template <typename T>
void process(const T& value)
noexcept(noexcept(declval<T>().size()))
{
// Try to call the size() member function of T
// If T's size() can throw, this function won't be
// noexcept for T
// If T's size() is noexcept, this
// function will be noexcept for T
cout << "Size: " << value.size() << endl;
}
// main function
int main()
{
vector<int> numbers = { 1, 2, 3, 4, 5 };
// Won't throw exceptions for std::vector
process(numbers);
// May throw exceptions for int
process(42);
return 0;
}
什么时候使用noexcept?
- 确认不会抛出异常的函数:包括其调用的所有函数都不会抛出异常,那就可以标记其为
noexcept
,适用于简单的访问函数、数学运算函数或者只包含基本类型操作的函数 - 移动构造函数和移动赋值运算符:这些特殊成员函数应当尽可能地标记为
noexcept
。因为它们在资源管理(如智能指针的转移)中非常重要,且不应失败。如果移动操作可能抛出异常,容器和其他代码可能会回退到较慢的复制操作上,影响性能。
关于什么是移动构造函数以及移动赋值运算符,可以看这篇文章:
C++--移动构造函数以及移动赋值运算符