在C++里,异常处理是保障程序健壮性的关键手段,主要通过 try、catch 和 throw 三个关键字来实现。这套机制允许我们在运行时捕获并处理错误,而不是直接让程序崩溃。下面就来聊聊它的基本概念和常见用法。

基本概念
- try块:包裹那些可能抛出异常的代码。
- catch块:捕获并处理特定类型的异常。
- throw表达式:主动抛出异常。
使用方法
1. 基本的try-catch结构
一个最简单的例子:在 try 块中抛出异常,然后在 catch 块中捕获并处理它。注意,catch (...) 可以捕获所有类型的异常,但通常建议尽量指定具体类型。
#include
#include
int main() {
try {
// 可能抛出异常的代码
throw std::runtime_error("An error occurred");
} catch (const std::runtime_error& e) {
// 捕获并处理std::runtime_error类型的异常
std::cerr << "Caught exception: " << e.what() << std::endl;
} catch (...) {
// 捕获所有其他类型的异常
std::cerr << "Caught an unknown exception" << std::endl;
}
return 0;
}
2. 多个catch块
实际开发中,不同异常往往需要不同处理逻辑。你可以为不同类型的异常分别提供 catch 块,编译器会从上到下匹配,找到第一个匹配的块执行。
try {
// 可能抛出异常的代码
throw std::runtime_error("An error occurred");
} catch (const std::runtime_error& e) {
std::cerr << "Caught runtime_error: " << e.what() << std::endl;
} catch (const std::logic_error& e) {
std::cerr << "Caught logic_error: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Caught an unknown exception" << std::endl;
}
3. 抛出异常
使用 throw 关键字可以随时主动抛出异常,比如在检测到非法参数时。下面的 divide 函数在被零除时抛出 runtime_error,由调用方通过 try-catch 处理。
void divide(int a, int b) {
if (b == 0) {
throw std::runtime_error("Division by zero");
}
return a / b;
}
int main() {
try {
divide(10, 0);
} catch (const std::runtime_error& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
4. 异常规范(Deprecated)
在C++11之前,异常规范(如 throw())曾被用来声明函数可能抛出的异常类型,但后来发现这套机制在实践中并不好用,于是C++11将其弃用,C++17直接移除。推荐使用 noexcept 关键字明确指定函数是否会抛出异常:
void divide(int a, int b) noexcept(false) {
if (b == 0) {
throw std::runtime_error("Division by zero");
}
return a / b;
}
这里 noexcept(false) 表示该函数可能抛出异常,而 noexcept(true) 则表示绝对不会抛出。
异常处理的注意事项
- 资源管理:异常发生时,栈上对象的析构函数会自动调用,但动态分配的资源(如堆内存、文件句柄)需要特别小心。推荐使用RAII(Resource Acquisition Is Initialization)技术,将资源封装在对象中,利用构造/析构自动管理。
- 性能考虑:异常处理确实会带来一定的运行时开销,尤其是在异常路径被频繁触发时。因此不建议把异常当作普通的流程控制工具,它更适合处理那些真正“异常”的情况。
- 异常安全性:确保抛出异常时程序状态保持一致,不会出现资源泄露、数据破坏等问题。这是编写高质量C++代码的基本素养。
合理运用C++的异常处理机制,能让程序在面对意外情况时更从容,整体健壮性和可维护性也会明显提升。当然,没有银弹——具体场景需要仔细权衡,但掌握这套工具,绝对是值得的。