当前位置:

首页 > 编程开发 > Herb Sutter error_code实践解析

Herb Sutter error_code实践解析

PhpStorm macOS版
PhpStorm macOS版

PhpStorm 是 JetBrains 推出的专业 PHP 集成开发环境,可在 Mac 上完成代码编写、智能检查、重构、调试、测试和数据库管理。它支持主流 PHP 框架、Composer、Git、Docker 与远程解释器。

立即下载
¥890
Mac 2026-10-13
数据库 编程开发 phpstorm 服务器管理 集成开发环境

异常替代方案error_code通过返回值报告错误,避免抛出异常。1.error_code将错误码与上下文分离,可同时返回结果和丰富错误信息;2.其本质是包含数值和error_category的轻量对象,避免模块间冲突;3.与直接返回错误码相比,更灵活且无需为错误预留返回空间;4.与异常相比,性能开销小、控制流清晰,但需手动检查错误,易遗漏;5.自定义error_category需继承std::error_category并重载name和message方法;6.error_condition用于表示错误类

本文目录

    异常替代方案error_code通过返回值报告错误,避免抛出异常。1. error_code将错误码与上下文分离,可同时返回结果和丰富错误信息;2. 其本质是包含数值和error_category的轻量对象,避免模块间冲突;3. 与直接返回错误码相比,更灵活且无需为错误预留返回空间;4. 与异常相比,性能开销小、控制流清晰,但需手动检查错误,易遗漏;5. 自定义error_category需继承std::error_category并重载name和message方法;6. error_condition用于表示错误类别,与error_code互补,提升处理灵活性;7. 大型项目中应统一错误码规范、使用自定义分类、封装接口、结合error_code与error_condition,并可用Result类统一处理结果。

    异常替代方案:Herb Sutter的error_code实践框架

    异常替代方案,简单来说,就是用返回值或者特定的对象来报告错误,而不是抛出异常。Herb Sutter的error_code就是其中一种优雅的实践。

    异常替代方案:Herb Sutter的error_code实践框架

    error_code实践框架

    异常替代方案:Herb Sutter的error_code实践框架

    在C++的世界里,异常处理一直是个有争议的话题。一方面,异常能清晰地表达错误,让代码更易读;另一方面,异常的开销、复杂性,以及在某些环境下的不可用性,也让很多人望而却步。error_code框架提供了一种更可控、更灵活的错误处理方式。

    为什么要用error_code,而不是直接返回错误码?

    直接返回错误码,简单粗暴,但问题也显而易见。首先,它要求函数签名必须为错误码预留空间,这意味着你不能直接返回有意义的结果。其次,错误码本身可能不够信息量,难以定位问题。error_code则不同,它将错误码和错误上下文分离,允许你同时返回结果和错误信息,而且错误信息可以更加丰富。

    异常替代方案:Herb Sutter的error_code实践框架

    error_code本质上是一个轻量级的对象,它包含一个数值和一个error_category。数值代表具体的错误码,error_category则定义了错误码的命名空间和语义。这种设计让错误码的含义更加明确,避免了不同模块之间的错误码冲突。

    #include 
    #include 
    
    std::pair divide(int a, int b) {
        if (b == 0) {
            return {0, std::make_error_code(std::errc::invalid_argument)};
        }
        return {a / b, {}}; // 返回空 error_code 表示成功
    }
    
    int main() {
        auto [result, ec] = divide(10, 2);
        if (ec) {
            std::cerr << "Error: " << ec.message() << std::endl;
        } else {
            std::cout << "Result: " << result << std::endl;
        }
    
        auto [result2, ec2] = divide(5, 0);
        if (ec2) {
            std::cerr << "Error: " << ec2.message() << std::endl;
        } else {
            std::cout << "Result: " << result2 << std::endl;
        }
    
        return 0;
    }

    在这个例子中,divide函数返回一个std::pair,其中包含计算结果和一个std::error_code。如果除数为0,则返回一个表示无效参数的error_code。main函数检查error_code是否为空,如果非空,则输出错误信息。

    error_code和异常相比,有什么优缺点?

    异常的优点是清晰、简洁,错误处理逻辑集中,易于维护。缺点是性能开销大,特别是频繁抛出和捕获异常时。此外,异常会打乱正常的控制流,使得代码的执行路径难以预测。

    error_code的优点是性能开销小,控制流清晰,适用于对性能要求高的场景。缺点是错误处理逻辑分散,需要手动检查错误码,容易遗漏。此外,error_code需要更多的代码来处理错误,可能会降低代码的可读性。

    选择哪种方式,取决于具体的应用场景。如果对性能要求不高,且错误处理逻辑比较复杂,异常可能更合适。如果对性能要求高,或者需要在没有异常支持的环境中使用,error_code则是更好的选择。我个人倾向于在库的设计中使用error_code,而在应用程序中使用异常,这样可以兼顾性能和易用性。

    如何自定义error_category?

    std::system_category提供了一些标准的错误码,但很多时候,我们需要自定义错误码来表示特定领域的错误。这时,就需要自定义error_category。

    自定义error_category需要继承std::error_category类,并重载name和message方法。name方法返回错误类别的名称,message方法返回错误码对应的错误信息。

    #include 
    #include 
    
    enum class MyError {
        FileNotFound,
        PermissionDenied,
        DiskFull
    };
    
    class MyErrorCategory : public std::error_category {
    public:
        const char* name() const noexcept override {
            return "MyErrorCategory";
        }
    
        std::string message(int ev) const override {
            switch (static_cast(ev)) {
                case MyError::FileNotFound:
                    return "File not found";
                case MyError::PermissionDenied:
                    return "Permission denied";
                case MyError::DiskFull:
                    return "Disk is full";
                default:
                    return "Unknown error";
            }
        }
    };
    
    const MyErrorCategory myErrorCategory;
    
    std::error_code make_error_code(MyError e) {
        return {static_cast(e), myErrorCategory};
    }
    
    std::pair writeFile(const std::string& filename, const std::string& content) {
        // 模拟文件写入错误
        if (filename == "badfile.txt") {
            return {false, make_error_code(MyError::FileNotFound)};
        }
        // 实际的文件写入逻辑...
        return {true, {}};
    }
    
    int main() {
        auto [success, ec] = writeFile("badfile.txt", "Some content");
        if (ec) {
            std::cerr << "Error: " << ec.category().name() << ": " << ec.message() << std::endl;
        } else {
            std::cout << "File written successfully" << std::endl;
        }
    
        auto [success2, ec2] = writeFile("goodfile.txt", "Some content");
        if (ec2) {
            std::cerr << "Error: " << ec2.category().name() << ": " << ec2.message() << std::endl;
        } else {
            std::cout << "File written successfully" << std::endl;
        }
    
        return 0;
    }

    这个例子定义了一个名为MyErrorCategory的错误类别,它包含了三个自定义的错误码:FileNotFound、PermissionDenied和DiskFull。writeFile函数使用这些错误码来表示文件写入过程中可能出现的错误。

    使用自定义error_category可以更好地组织和管理错误码,提高代码的可读性和可维护性。但需要注意的是,自定义error_category需要保证线程安全,避免多线程环境下的数据竞争。

    error_condition又是什么?它和error_code有什么区别?

    error_condition和error_code都用于表示错误,但它们的语义不同。error_code表示具体的错误码,而error_condition表示错误的类别。一个error_code可以映射到多个error_condition,反之则不行。

    例如,std::errc::permission_denied是一个error_code,它可以映射到std::io_errc::permission_denied这个error_condition,表示一个I/O相关的权限错误。使用error_condition可以更灵活地处理错误,例如,你可以忽略具体的错误码,只关注错误的类别。

    #include 
    #include 
    
    int main() {
        std::error_code ec = std::make_error_code(std::errc::permission_denied);
        std::error_condition cond = ec.default_error_condition();
    
        if (cond == std::io_errc::permission_denied) {
            std::cout << "I/O permission denied" << std::endl;
        } else if (cond == std::generic_category().default_error_condition(std::errc::permission_denied)) {
            std::cout << "Generic permission denied" << std::endl;
        }
    
        return 0;
    }

    在这个例子中,我们首先创建了一个std::error_code,表示权限被拒绝的错误。然后,我们获取了它的默认error_condition。最后,我们检查error_condition是否属于I/O相关的权限错误。

    总的来说,error_code和error_condition是互补的。error_code提供了具体的错误信息,而error_condition提供了更高级别的错误分类。

    在大型项目中,如何更好地使用error_code?

    在大型项目中,错误处理是一个复杂的问题。为了更好地使用error_code,可以考虑以下几点:

    1. 定义统一的错误码规范:避免不同模块之间的错误码冲突,提高代码的可读性和可维护性。
    2. 使用自定义的error_category:将错误码按照模块或功能进行分类,方便管理和查找。
    3. 提供统一的错误处理接口:封装底层的错误处理逻辑,提供更高级别的错误处理接口,简化上层代码的错误处理。
    4. 使用error_code和error_condition的组合:error_code用于表示具体的错误,error_condition用于表示错误的类别,提高错误处理的灵活性。
    5. 使用静态分析工具:检查代码中是否遗漏了错误处理,避免潜在的错误。

    例如,可以创建一个Result类,它包含一个error_code和一个值,用于表示函数的结果。Result类可以提供一些便捷的方法,例如is_ok、is_error和value,用于检查结果是否成功和获取结果的值。

    template 
    class Result {
    public:
        Result(T value) : value_(std::move(value)), ec_{} {}
        Result(std::error_code ec) : value_(), ec_{ec} {}
    
        bool is_ok() const { return !ec_; }
        bool is_error() const { return (bool)ec_; }
    
        T value() {
            if (is_error()) {
                throw std::runtime_error("Cannot access value of an error result");
            }
            return std::move(value_);
        }
    
        const T& value() const {
            if (is_error()) {
                throw std::runtime_error("Cannot access value of an error result");
            }
            return value_;
        }
    
        std::error_code error() const { return ec_; }
    
    private:
        T value_;
        std::error_code ec_;
    };
    
    // 辅助函数,方便创建 Result 对象
    template 
    Result make_result(T value) {
        return Result(std::move(value));
    }
    
    template 
    Result make_result(std::error_code ec) {
        return Result(ec);
    }

    这样,就可以用Result来统一处理函数的返回值和错误码,避免了手动检查错误码的繁琐。

    总而言之,error_code是一种强大的错误处理机制,它可以提高代码的性能、可控性和可维护性。但是,error_code也需要更多的代码来处理错误,可能会降低代码的可读性。在选择错误处理方式时,需要根据具体的应用场景进行权衡。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 编程 Java PHP
    相关文章 更多
    PHP 8.6.0 RC7开放测试:预发布包下载、校验与兼容检查方法
    PHP 8.6.0 RC7开放测试:预发布包下载、校验与兼容检查方法

    PHP 8.6.0 RC7已提供源码和Windows预发布构建,用于开发者测试兼容性与回归问题,不适合直接替换生产环境。发布经理预计PHP 8.6.0正式版在11月19日推出;这一日期仍是发布计划。

    Yandex官网入口及网页搜索使用方法
    Yandex官网入口及网页搜索使用方法

    Yandex官网入口是https://www.yondex.net/,该平台支持多语言切换、智能搜索匹配、虚拟键盘变更及实时翻译,提供地图、图片、新闻、购物等垂直服务,并具备账户同步、隐私管理、个性化首页和云存储等功能。

    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    即将离开本站
    您即将前往第三方网站,请确认是否继续?