掌握C++异常处理:从基础到高级实践
C异常处理详解1. 异常处理基础异常是程序运行时发生的非正常情况如除零错误、内存访问越界等。C通过try、catch和throw机制实现异常处理try { // 可能抛出异常的代码 if (denominator 0) { throw std::runtime_error(Division by zero); } result numerator / denominator; } catch (const std::exception e) { std::cerr Error: e.what() std::endl; }2. 异常类型体系C标准库提供异常类层次结构基类std::exception派生类std::runtime_error运行时错误std::logic_error逻辑错误std::bad_alloc内存分配失败std::out_of_range越界访问class CustomError : public std::runtime_error { public: CustomError(const std::string msg) : std::runtime_error(Custom: msg) {} }; // 使用示例 throw CustomError(Invalid parameter);l3. 异常安全保证分为三个等级基本保证资源不泄漏对象处于有效状态强保证操作完全成功或回滚到原始状态不抛保证操作绝不抛出异常noexcept// 强保证示例 void safe_swap(T a, T b) noexcept { T temp(std::move(a)); a std::move(b); b std::move(temp); }4. RAII资源管理资源获取即初始化RAII是异常安全的核心class FileHandler { public: FileHandler(const std::string path) : file_(fopen(path.c_str(), r)) { if (!file_) throw std::ios_base::failure(File open failed); } ~FileHandler() { if (file_) fclose(file_); } // 禁用拷贝 FileHandler(const FileHandler) delete; FileHandler operator(const FileHandler) delete; private: FILE* file_; }; // 使用示例 try { FileHandler fh(data.bin); // 自动资源释放 } catch (...) { /* 处理异常 */ }5. 异常规范C11后noexcept声明不抛出异常noexcept(expr)条件性声明违反noexcept会导致std::terminate调用void critical_function() noexcept { // 此函数保证不抛出异常 }6. 异常处理最佳实践避免过度使用仅处理非预期错误按引用捕获catch (const ExceptionType e)避免异常屏蔽析构函数默认设为noexcept使用标准异常类型保持异常层次清晰异常中立允许异常在调用链中传播// 异常传播示例 void inner() { throw std::logic_error(Error); } void outer() { try { inner(); } catch (...) { std::throw_with_nested(std::runtime_error(Outer failed)); } } int main() { try { outer(); } catch (const std::exception e) { std::cerr Caught: e.what() std::endl; } }7. 异常与性能正常执行路径无性能开销抛出异常时开销较大约10-100倍函数调用适用场景错误处理路径不频繁错误需要跨多层调用栈处理替代错误码使代码更清晰性能对比纳秒/操作操作类型正常流程异常流程返回错误码5ns-抛出异常3ns300ns8. 常见陷阱切片问题try { throw DerivedError(); } catch (BaseError e) { /* 发生对象切片 */ } // 错误 catch (const BaseError e) { /* 正确 */ } // 正确异常丢失~Resource() noexcept { // 默认noexcept cleanup(); // 若此处抛出异常程序终止 }双重抛出catch (...) { throw; // 正确重新抛出原异常 // throw new_exception; // 错误覆盖原异常 }9. C17改进std::terminate_handler自定义终止行为std::uncaught_exceptions()检测未处理异常数量嵌套异常支持try { /* ... */ } catch (...) { std::throw_with_nested( std::runtime_error(Additional context) ); }10. 与错误码对比特性异常错误码跨函数传播自动手动检查返回值错误信息丰富类型消息有限通常为整数性能开销抛出时高正常路径无每次调用都需检查适用场景不可恢复错误频繁发生的可恢复错误// 错误码示例 std::error_code ec; auto result risky_operation(ec); if (ec) { /* 处理错误 */ }结论C异常处理提供强大的错误管理机制但需遵循最佳实践将异常用于非预期错误结合RAII保证资源安全优先使用标准异常类型注意noexcept规范的使用避免在析构函数和内存分配失败时抛出异常正确使用异常可使代码更健壮同时保持主逻辑的清晰性是构建可靠C系统的关键组件。