个人主页星柚程精选文章《MATLAB多目标优化》《Kaggle:CV、Public LB 》、《我的第一次 Kaggle》、《C构造传参》、《蛇形机械臂的模拟退火优化》️专栏建设|深度学习|、|Python量化|、|C学习|、|数据结构|流水不争先争得是涛涛不绝。引言对于无法在本地恢复、需要向上传播或由统一层处理的异常场景推荐使用 try-catch。对性能敏感、频繁调用或与 C 接口交互的场合推荐使用错误码或 std::optional/std::expected 等显式返回策略。详细解析异常try-catch方式优点将错误处理与业务逻辑分离主流程更简洁可以跨多个调用层级向上传播错误无需每层都检查返回值标准库和许多现代库如filesystem、std::thread都使用异常报告错误。缺点性能开销抛出和捕获异常代价较高不宜在热路径或频繁错误场景使用控制流不直观过度依赖异常可能让代码阅读和调试更难需要在项目中统一规范否则不同模块混用容易遗漏捕获。适用场景系统初始化失败、配置文件解析失败、资源分配失败等“异常”情况业务逻辑中确实无法就地处理的错误需要由上层统一拦截并处理。错误码 / 显式返回优点开销小调用者直接通过返回值判断并处理流程清晰调用者立刻看到可能的错误分支易于与 C 接口或性能敏感代码混用。缺点业务逻辑容易被大量的if (err) return err;打断可读性下降容易忽略错误码检查导致隐性错误。改进方式使用enum class ErrorCode或std::error_code进行类型安全的错误码C23 引入std::expectedT, E可同时携带返回值和错误信息简化处理。适用场景性能关键的底层库、频繁调用的循环体、跨语言边界C/C 混编简单的验证或业务分支如查找不到元素时返回nullptr或错误码。混合使用与团队规范在同一项目或模块中选择一种主要方式并制定规范对于公共接口若库面向 C 用户且错误较少、复杂度高可用异常若面向 C 用户或嵌入式场景则用错误码内部实现可用错误码接口抛出异常借助适配层统一转换。示例代码#include iostream #include stdexcept #include optional #include system_error // 异常方式 int divideException(int a, int b) { if (b 0) throw std::runtime_error(除以零错误); return a / b; } // 错误码方式 enum class ErrorCode { Ok, DivideByZero }; std::pairErrorCode,int divideErrorCode(int a, int b) { if (b 0) return {ErrorCode::DivideByZero, 0}; return {ErrorCode::Ok, a / b}; } int main() { // 异常处理 try { std::cout 10 / 2 divideException(10,2) std::endl; auto res divideException(10,0); std::cout 10 / 0 res std::endl; } catch (const std::exception e) { std::cout 捕获异常: e.what() std::endl; } // 错误码处理 auto [ec1, res1] divideErrorCode(10,2); if (ec1 ErrorCode::Ok) std::cout 10 / 2 res1 std::endl; else std::cout 错误码方式除以零 std::endl; auto [ec2, res2] divideErrorCode(10,0); if (ec2 ErrorCode::Ok) std::cout 10 / 0 res2 std::endl; else std::cout 错误码方式除以零 std::endl; return 0; }运行结果10 / 2 5捕获异常: 除以零错误10 / 2 5错误码方式除以零代码解读divideException在除数为零时抛出std::runtime_error由调用者在try-catch块中捕获并处理divideErrorCode返回一个(ErrorCode, int)对让调用者显式检查ErrorCode并处理错误。
[C++]错误码与Try-catch
个人主页星柚程精选文章《MATLAB多目标优化》《Kaggle:CV、Public LB 》、《我的第一次 Kaggle》、《C构造传参》、《蛇形机械臂的模拟退火优化》️专栏建设|深度学习|、|Python量化|、|C学习|、|数据结构|流水不争先争得是涛涛不绝。引言对于无法在本地恢复、需要向上传播或由统一层处理的异常场景推荐使用 try-catch。对性能敏感、频繁调用或与 C 接口交互的场合推荐使用错误码或 std::optional/std::expected 等显式返回策略。详细解析异常try-catch方式优点将错误处理与业务逻辑分离主流程更简洁可以跨多个调用层级向上传播错误无需每层都检查返回值标准库和许多现代库如filesystem、std::thread都使用异常报告错误。缺点性能开销抛出和捕获异常代价较高不宜在热路径或频繁错误场景使用控制流不直观过度依赖异常可能让代码阅读和调试更难需要在项目中统一规范否则不同模块混用容易遗漏捕获。适用场景系统初始化失败、配置文件解析失败、资源分配失败等“异常”情况业务逻辑中确实无法就地处理的错误需要由上层统一拦截并处理。错误码 / 显式返回优点开销小调用者直接通过返回值判断并处理流程清晰调用者立刻看到可能的错误分支易于与 C 接口或性能敏感代码混用。缺点业务逻辑容易被大量的if (err) return err;打断可读性下降容易忽略错误码检查导致隐性错误。改进方式使用enum class ErrorCode或std::error_code进行类型安全的错误码C23 引入std::expectedT, E可同时携带返回值和错误信息简化处理。适用场景性能关键的底层库、频繁调用的循环体、跨语言边界C/C 混编简单的验证或业务分支如查找不到元素时返回nullptr或错误码。混合使用与团队规范在同一项目或模块中选择一种主要方式并制定规范对于公共接口若库面向 C 用户且错误较少、复杂度高可用异常若面向 C 用户或嵌入式场景则用错误码内部实现可用错误码接口抛出异常借助适配层统一转换。示例代码#include iostream #include stdexcept #include optional #include system_error // 异常方式 int divideException(int a, int b) { if (b 0) throw std::runtime_error(除以零错误); return a / b; } // 错误码方式 enum class ErrorCode { Ok, DivideByZero }; std::pairErrorCode,int divideErrorCode(int a, int b) { if (b 0) return {ErrorCode::DivideByZero, 0}; return {ErrorCode::Ok, a / b}; } int main() { // 异常处理 try { std::cout 10 / 2 divideException(10,2) std::endl; auto res divideException(10,0); std::cout 10 / 0 res std::endl; } catch (const std::exception e) { std::cout 捕获异常: e.what() std::endl; } // 错误码处理 auto [ec1, res1] divideErrorCode(10,2); if (ec1 ErrorCode::Ok) std::cout 10 / 2 res1 std::endl; else std::cout 错误码方式除以零 std::endl; auto [ec2, res2] divideErrorCode(10,0); if (ec2 ErrorCode::Ok) std::cout 10 / 0 res2 std::endl; else std::cout 错误码方式除以零 std::endl; return 0; }运行结果10 / 2 5捕获异常: 除以零错误10 / 2 5错误码方式除以零代码解读divideException在除数为零时抛出std::runtime_error由调用者在try-catch块中捕获并处理divideErrorCode返回一个(ErrorCode, int)对让调用者显式检查ErrorCode并处理错误。