C++要求catch必须声明异常类型,空catch是语法错误;应使用catch(...)捕获所有异常,或catch(const std::exception& e)捕获标准异常,避免对象切片。

catch 里为什么不能只写 catch 不带类型?
因为 C++ 要求每个 catch 必须明确声明它能捕获的异常类型,空 catch 是语法错误。编译器无法推断你想抓什么,也不允许“盲目兜底”。
常见错误现象:catch { ... } 直接报错 expected type-specifier before '{'。
- 想捕获所有异常,得用
catch (...)(注意三个点) - 想捕获标准异常,优先用
catch (const std::exception& e),避免对象切片 - 自定义异常类型要确保继承自
std::exception或至少支持拷贝/移动,否则throw可能失败
throw 表达式后面跟变量还是临时对象?
推荐 throw 临时对象,比如 throw std::runtime_error("file not found");,而不是先构造再 throw。
原因:C++17 起 guaranteed copy elision 让这种写法零开销;而如果写成 auto e = std::runtime_error("..."); throw e;,可能触发一次不必要的拷贝或移动(尤其在旧标准下)。
立即学习“C++免费学习笔记(深入)”;
- 不要 throw 局部变量的引用或指针(
throw &x;),栈展开后地址失效 - 避免 throw 大对象(如
std::vector),除非确定 catch 端会 move 它 - 函数声明里
throw()(动态异常规范)已弃用,C++11 起该用noexcept
try-catch 放在 main 里能捕获所有异常吗?
不能。main 函数外抛出的异常、线程里未捕获的异常、静态初始化期间的异常,都不会被 main 里的 try-catch 捕获。
典型场景:全局对象构造函数里 throw,程序直接调用 std::terminate,不会进 main 的 catch。
- 多线程中,每个线程需独立处理异常;主线程 catch 不到子线程的异常
- 信号(如 SIGSEGV)不是 C++ 异常,
try-catch完全无效,得用signal或sigsetjmp - 析构函数里 throw 是危险操作,可能引发
std::terminate(除非当前已处于栈展开中)
为什么有时候 catch 到的异常信息是空的?
常见于用了 catch (std::exception e)(传值)而非 catch (const std::exception& e)(传引用),导致派生类信息被切片,e.what() 返回空或默认字符串。
另一个原因是 throw 的对象本身没重写 what(),比如直接 throw "c-string",那 catch 时只能用 catch (const char*),且无法统一用 what() 接口。
- 永远优先用
const T&捕获,避免切片和额外拷贝 - 自定义异常务必重写
what()并确保返回指向生命周期足够的 C 字符串 - 调试时可加
std::cerr ,但生产环境别依赖 <code>what()做逻辑分支
noexcept 违反的处理方式、甚至 RTTI 是否启用都影响 catch 行为。真要靠异常做关键错误恢复,得实测目标平台的行为,不能只看标准描述。










