catch完全失效于系统级错误(如段错误、除零trap),因这些不触发c++异常机制;throw必须匹配catch类型,要求相同、公有继承或可调用拷贝/移动构造;推荐catch引用以避免二次异常;raii是异常安全唯一可靠路径;noexcept函数抛异常直接terminate。

能用 try-catch 捕获的,只有真正被 throw 抛出的 C++ 异常;系统级错误(如空指针解引用、除零)默认不会触发 catch,除非编译器开启特定异常机制(如 Windows SEH 转换)。
什么时候 catch 会完全失效?
常见误解是“catch(...) 能抓一切”,实际它只捕获 C++ 异常对象,对以下情况完全无感:
- 访问野指针或
nullptr导致的段错误(SIGSEGV),Linux/macOS 下直接进程终止 -
int x = 1 / 0;—— 这是 CPU 级别 trap,C++ 标准不定义其为异常 - 栈溢出、内存耗尽(
new失败时若没开nothrow,才会抛std::bad_alloc)
验证方式:写个 throw 42; 能被捕获;但 *(int*)0 = 1; 会直接 crash,catch(...) 压根没机会运行。
throw 表达式必须匹配 catch 类型吗?
必须——但匹配规则比表面严格。不是“能转就行”,而是要求类型相同、公有继承、或有可调用的拷贝/移动构造函数:
-
throw std::runtime_error("msg");→ 可被catch(std::exception& e)捕获(公有继承) -
throw "hello";→ 只能被catch(const char*)捕获,catch(std::string)不行(隐式转换不参与匹配) -
throw 3.14;→catch(int)捕不到,catch(double)才行
建议始终抛 std::exception 派生类,避免基础类型传递导致的切片或生命周期问题。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
为什么 catch 参数推荐用引用?
值传递会触发异常对象拷贝,可能抛新异常(比如拷贝构造函数里 new 失败),导致栈展开中断、程序终止:
class BadCopy {
public:
BadCopy() = default;
BadCopy(const BadCopy&) { throw std::runtime_error("copy failed"); }
};
// ...
try {
throw BadCopy{};
} catch(BadCopy b) { /* 这里会二次崩溃 */ }
正确写法:
-
catch(const std::exception& e)—— 安全、高效、支持多态 - 避免
catch(std::exception e)(值传递)和catch(std::exception&& e)(仅匹配右值,漏掉大部分情况)
资源泄漏风险:throw 发生在构造函数里怎么办?
构造函数中途 throw,已构造的成员会自动析构,但裸指针、文件描述符等不会:
- 错例:
FILE* fp = fopen("x.txt", "r"); if (!fp) throw std::runtime_error("open fail");——fopen成功后若后续 throw,fp泄漏 - 正解:用 RAII 封装,如
std::unique_ptr<file int></file>或std::ifstream - 更彻底:把资源获取逻辑移到工厂函数中,构造函数只做轻量初始化
记住:C++ 异常安全的唯一可靠路径是 RAII,不是靠 try-catch 到处兜底。
最易被忽略的一点:noexcept 函数里如果意外抛出异常,程序会立刻调用 std::terminate,连 catch(...) 都来不及触发——检查第三方库接口是否标记 noexcept,比写 try 更关键。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!








