优先用 const std::exception&,别用 std::exception 值传参;值传递会触发拷贝构造,可能导致异常对象切片、二次异常或 std::terminate,而 const 引用安全高效且保留多态性。

catch 块里该用 const 引用还是值传递?
直接说结论:优先用 const std::exception&,别用 std::exception 值传参。值传递会触发异常对象的拷贝构造,而某些异常类(比如自定义异常)可能没实现或禁用了拷贝;更糟的是,如果拷贝过程本身抛异常,程序直接调用 std::terminate() 终止。
- 用
catch (const std::exception& e)安全、高效,能访问基类接口(如e.what()) - 避免
catch (std::exception e)—— 无必要拷贝,且隐藏了移动语义优化机会 - 若需修改异常状态(极少见),才考虑非 const 引用
catch (std::exception& e),但要清楚风险
throw 表达式里 new 出来的对象会泄漏吗?
会。C++ 标准规定:throw 表达式求值后,若抛出的是指针(如 throw new MyException()),那这个堆对象永远不会被自动释放——因为 catch 块拿到的是指针副本,没人负责 delete。
- 永远不要
throw new XxxException() - 正确做法是抛值:
throw MyException("msg"),让异常对象在栈上构造、由运行时管理生命周期 - 如果真需要动态构造(例如带复杂初始化逻辑),改用
std::make_exception_ptr()+std::rethrow_exception(),但这是高级场景,日常不用
多个 catch 块的顺序为什么不能乱?
因为匹配是按代码书写顺序从上到下尝试的,一旦命中就停止匹配。如果把基类写在派生类前面,派生类永远没机会被捕获。
- 必须把更具体的异常类型放前面,通用类型(如
std::exception)放最后 - 错误示例:
catch (const std::exception& e) { ... } catch (const std::runtime_error& e) { ... }—— 后者永不会执行 - 正确顺序:
catch (const std::runtime_error& e)→catch (const std::logic_error& e)→catch (const std::exception& e) - 注意:
catch (...)是兜底,必须放在所有 typed catch 之后,否则它会截断所有其他类型
函数声明里的 noexcept 和 throw() 有什么区别?
throw() 是 C++98/03 的异常规范,已被弃用;noexcept 是 C++11 起的标准替代,语义更清晰、编译器优化更友好。
立即学习“C++免费学习笔记(深入)”;
-
void f() noexcept;表示承诺不抛任何异常;若违反,调用std::terminate() -
void f() noexcept(true)等价于noexcept;noexcept(false)表示可能抛异常(等价于不写) - 别用
throw()—— 它在 C++17 中已移除,现代编译器会警告 - 析构函数默认是
noexcept,显式写出来更明确,尤其当内部调用可能抛异常的函数时,得手动加noexcept(false)
catch 里又抛新异常却没处理旧异常的上下文。这些没法靠 try-catch 自动解决,得靠设计习惯。


















