c++怎么处理异常_c++try-catch语句用法【报错】

2次阅读

必须用 const std::exception& 捕获,否则按值捕获会导致派生类对象切片析构函数抛异常会调用 std::terminate;未捕获异常在 main 外直接终止程序;异常不可跨线程传播;std::String 构造不保证抛异常,空指针为未定义行为。

c++怎么处理异常_c++try-catch语句用法【报错】

catch 捕获不到 std::exception 子类?检查抛出对象是不是临时对象被切片了

常见现象是:明明 throw std::runtime_error("msg"),但 catch (std::exception e) 里拿到的却是空消息或崩溃。问题出在按值捕获——std::exception 是基类,按值传参会触发对象切片,丢失派生类信息。

  • 必须用引用捕获:catch (const std::exception& e),否则所有子类(std::runtime_errorstd::logic_error 等)都会被截断
  • 不要写 catch (std::exception e)catch (std::exception* e)(后者根本捕不到上抛出的对象)
  • 如果想捕获所有异常,catch (...) 可以兜底,但它不提供任何错误信息,不能直接调 e.what()

try-catch 放错位置导致程序直接 terminate

c++ 异常未被捕获时会调用 std::terminate,进程退出且不打印栈。这不是 bug,是标准行为——说明你漏写了某层 catch,或者异常从析构函数里逃出来了。

  • 析构函数默认是 noexcept 的,如果里面抛异常(比如 std::ofstream 关闭失败),会立即调 std::terminate;务必用 noexcept(false) 显式标注,或改用 try/catch 在内部处理
  • 全局 main() 函数外没 try 块,任何未捕获异常都会终止;建议在 main() 开头加一层 try { ... } catch (...) { return 1; } 防止静默崩溃
  • 多线程中,异常只在抛出它的线程内传播;其他线程里的 try 对它完全无效

为什么 std::string 构造失败会抛 std::bad_alloc 而不是 std::invalid_argument

这是 C++ 标准库实现细节决定的:内存分配失败统一走 std::bad_alloc,和参数合法性无关。别指望靠 catch std::invalid_argument 来处理空指针构造 std::string 这种情况。

  • std::string s(nullptr) 是未定义行为,不抛异常,可能直接段错误;必须先判空
  • std::string s(ptr, n) 中若 n 超过实际缓冲区长度,行为未定义;标准不保证抛异常
  • 真正会稳定抛 std::bad_alloc 的场景只有内存耗尽,比如 std::string(1024*1024*1024, 'x') 在小内存机器上

性能影响:频繁 throw/catch 会拖慢程序吗?

会,但仅限于“真的抛出并展开栈”的时候。try/catch 语句本身(没触发异常时)几乎零开销,现代编译器已优化掉大部分运行时负担。

立即学习C++免费学习笔记(深入)”;

  • 异常抛出是重量级操作:要遍历栈帧、调析构、找匹配 handler,比 if-else 判断慢 1–2 个数量级
  • 不要用异常做流程控制,比如用 throw 代替 return 表达“找不到”;该用 std::optional 或返回码就用
  • Release 模式下,异常处理机制仍存在,但部分调试信息(如符号名)会被剥离,what() 内容可能变简略

事情说清了就结束。异常机制本身不难,难的是判断哪些错误真该用它来表达——比如资源获取失败、协议解析错误这类“意外”,而不是“输入为空”这种可预期分支。

text=ZqhQzanResources