noexcept
可以放在函数声明或定义的后面,表示该函数不会抛出任何异常。如果函数在运行时抛出异常,程序会立即终止,并调用std::terminate()
函数。
特性:
noexcept
的函数在运行时抛出异常,程序会立即终止。代码示例:
#include
#include
void safeFunction() noexcept {
// 这个函数不会抛出异常
std::cout << "safeFunction called" << std::endl;
}
void unsafeFunction() {
// 这个函数可能会抛出异常
throw std::runtime_error("An error occurred");
}
int main() {
try {
safeFunction();
unsafeFunction(); // 这里会抛出异常
} catch (const std::exception& e) {
std::cerr << "Exception caught: " << e.what() << std::endl;
}
return 0;
}
输出:
safeFunction called
Exception caught: An error occurred
如果将unsafeFunction
标记为noexcept
:
void unsafeFunction() noexcept {
// 这个函数可能会抛出异常
throw std::runtime_error("An error occurred");
}
输出:
safeFunction called
terminate called after throwing an instance of 'std::runtime_error'
what(): An error occurred
程序会立即终止,并调用std::terminate()
。
noexcept(expression)
用于检查表达式是否可能抛出异常。如果表达式不会抛出异常,则返回true
;否则返回false
。
特性:
代码示例:
#include
#include
void safeFunction() noexcept {
std::cout << "safeFunction called" << std::endl;
}
void unsafeFunction() {
throw std::runtime_error("An error occurred");
}
int main() {
std::cout << "safeFunction noexcept: " << noexcept(safeFunction()) << std::endl;
std::cout << "unsafeFunction noexcept: " << noexcept(unsafeFunction()) << std::endl;
return 0;
}
输出:
safeFunction noexcept: 1
unsafeFunction noexcept: 0
标记为noexcept
的函数,编译器可以进行一些优化,例如删除异常处理代码、进行函数内联等,从而提高程序的性能。
代码示例:
#include
#include
void safeFunction() noexcept {
// 这个函数不会抛出异常
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
void unsafeFunction() {
// 这个函数可能会抛出异常
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
auto start = std::chrono::high_resolution_clock::now();
safeFunction();
auto end = std::chrono::high_resolution_clock::now();
std::cout << "safeFunction took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;
start = std::chrono::high_resolution_clock::now();
unsafeFunction();
end = std::chrono::high_resolution_clock::now();
std::cout << "unsafeFunction took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;
return 0;
}
输出:
safeFunction took 100 ms
unsafeFunction took 100 ms
虽然在这个简单的例子中性能差异不明显,但在复杂的程序中,noexcept
可以显著提高性能。
使用noexcept
可以提高代码的异常安全性。标记为noexcept
的函数不会抛出异常,因此调用这些函数的代码可以更加自信地使用不带RAII(资源获取即初始化)的代码。
代码示例:
#include
#include
class MyClass {
public:
MyClass(int value) : value_(value) {}
int value() const { return value_; }
// 移动构造函数
MyClass(MyClass&& other) noexcept : value_(other.value_) {
other.value_ = 0;
}
// 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
value_ = other.value_;
other.value_ = 0;
}
return *this;
}
private:
int value_;
};
void testMove() noexcept {
std::vector<MyClass> vec;
vec.reserve(10);
for (int i = 0; i < 10; ++i) {
vec.emplace_back(i);
}
std::vector<MyClass> vec2 = std::move(vec);
}
int main() {
testMove();
return 0;
}
在这个例子中,MyClass
的移动构造函数和移动赋值运算符都被标记为noexcept
,这使得std::vector
在进行内存重新分配等操作时可以安全地使用移动语义。
noexcept
是一个非常有用的特性,它可以帮助你编写更安全、更高效的代码。通过标记函数为noexcept
,你可以告诉编译器这些函数不会抛出异常,从而让编译器进行优化。同时,noexcept
也可以帮助你提高代码的异常安全性,特别是在使用移动语义时。