std::error_code是轻量级错误码快照,需主动检查处理,不可替代异常;正确用法是errno配std::system_category()构造,比较用std::errc枚举,避免直接比数值。

std::error_code 本质是错误码快照,不是异常
它不抛出、不中断执行,只存一个整数和对应分类(比如 std::system_category() 或 std::generic_category())。你得主动检查、主动处理。常见误用是把它当 std::exception_ptr 用,结果错误被静默吞掉。
典型场景:系统调用失败后想保留原始 errno,又不想立刻 throw;或者跨模块传递底层错误而不暴露异常机制。
-
std::error_code是可拷贝、可赋值的轻量对象,构造时不抛异常 - 必须显式初始化,否则值为
std::error_code()(即value() == 0且category() == std::generic_category()) - 不要用
std::error_code ec = errno;—— 这会绑定到std::generic_category(),而系统错误该用std::system_category()
正确捕获 errno 并转成 std::error_code
系统调用(如 open()、mkdir())失败后,errno 被设置,但 C++ 不自动帮你转。必须手动传入 errno 和 std::system_category()。
int fd = open("missing.txt", O_RDONLY);
if (fd == -1) {
std::error_code ec(errno, std::system_category()); // ✅ 正确
// ec.value() == errno, ec.category() == std::system_category()
}
- 漏掉
std::system_category()就会误用std::generic_category(),导致ec.message()返回“Success”或完全不对的字符串 - 某些平台(如 Windows MSVC)中,
errno可能被 CRT 调用覆盖,所以必须在系统调用**紧后**立即读取 - POSIX 函数返回 -1 表示失败,Windows API 返回 0 或 INVALID_HANDLE_VALUE,需按平台分别判断
比较与判断错误类型时,别直接比数值
不同系统上同一语义错误(如“文件不存在”)对应不同 errno 值:ENOENT 在 Linux 是 2,在 macOS 是 2,在 Windows 的 std::system_category() 下可能映射为 ERROR_PATH_NOT_FOUND(3)——但它们都等价于 std::errc::no_such_file_or_directory。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
所以应使用标准错误条件枚举比较:
if (ec == std::errc::no_such_file_or_directory) { ... } // ✅ 推荐
if (ec.value() == ENOENT) { ... } // ❌ 不跨平台
-
std::errc是 C++11 引入的标准化错误码枚举,覆盖常见 POSIX 错误 - 支持隐式转换:
std::error_code ec = std::errc::invalid_argument;自动绑定到std::generic_category() - 自定义错误类别时,也要重载
operator==并提供对应std::errc映射,否则比较失效
std::error_code 不能替代 std::exception 用于流程控制
它适合记录、转发、日志、返回给调用方做决策,但不适合驱动主逻辑分支。例如,你不该写:
if (ec) {
// 大段恢复逻辑……
}
因为 ec 本身不携带堆栈、上下文或可扩展信息。真正需要错误传播+恢复能力时,该用 std::system_error(它持有 std::error_code 并可抛出)。
-
std::system_error(ec, "open failed")是带描述的异常封装,适合向上抛 - 函数返回
std::error_code&参数是常见模式(如std::filesystem::create_directory),但调用方必须检查是否非空 - 用
std::error_code作函数返回值时,注意它默认构造是“无错误”,别依赖bool(ec)判断——要显式写if (ec),因为其有explicit operator bool()
最容易被忽略的是:std::error_code 没有移动语义优化,大量传递时注意别无意中触发冗余拷贝;更关键的是,它不保证线程安全——category() 的静态实例是全局的,但 error_code 对象本身是线程安全的。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










