写代码时总怕程序突然崩溃?尤其是处理文件、网络请求或者用户输入的时候,一个不小心就闪退。这时候,C++的异常捕获机制就能派上用场了。
什么是异常捕获
简单来说,异常捕获就是提前准备好“救火预案”。当程序运行中出现意料之外的情况,比如除以零、内存分配失败或者打开不存在的文件,程序不会直接崩掉,而是跳转到你指定的地方去处理问题。
try-catch 基本用法
核心结构是 try 和 catch 搭配使用。把可能出错的代码放进 try 块里,一旦抛出异常,就会被对应的 catch 捕获。
int main() {
try {
int a = 10, b = 0;
if (b == 0) {
throw std::runtime_error("除数不能为零");
}
int result = a / b;
} catch (const std::exception& e) {
std::cout << "捕获异常:" << e.what() << std::endl;
}
return 0;
}
上面这段代码,如果没有异常处理,程序会在除零时直接崩溃。用了 try-catch 后,错误被拦截,还能输出具体原因,用户体验就好多了。
捕获不同类型的异常
有些场景下需要区分不同错误类型。比如文件打不开和网络超时,处理方式不一样。C++允许你写多个 catch 分别处理。
try {
std::ifstream file("config.txt");
if (!file) {
throw std::ios_base::failure("文件无法打开");
}
// 读取配置...
} catch (const std::ios_base::failure& e) {
std::cerr << "文件错误:" << e.what() << std::endl;
} catch (const std::runtime_error& e) {
std::cerr << "运行时错误:" << e.what() << std::endl;
}
避免裸抛异常
直接 throw 字符串或整数虽然可行,但不好控制。推荐使用标准库中的异常类,比如 std::runtime_error、std::invalid_argument,这样更容易统一处理,也方便调试。
if (ptr == nullptr) {
throw std::invalid_argument("指针不能为空");
}
RAII 配合异常更安全
很多人担心异常会导致资源泄漏,比如忘了关文件、释放内存。其实只要合理使用 RAII(资源获取即初始化),对象在析构时自动清理,哪怕抛异常也不怕。
像 std::ifstream、std::vector 这些类都自带资源管理功能。用它们代替手动 new/delete 或 fopen/fclose,代码不仅更简洁,还更安全。