【C++23错误处理革命】:std::expected最佳实践全解析,告别传统异常开销

第一章:C++23错误处理的演进与std::expected概述

C++23引入了std::expected,标志着标准库在错误处理机制上的重大进步。该类型旨在替代传统的异常处理和std::optional组合使用的方式,提供一种更安全、更明确的错误传递方案。通过将成功值与错误信息封装在同一类型中,std::expected<T, E>允许开发者以函数式风格处理可能失败的操作。

设计动机与核心优势

传统异常处理在性能敏感或无异常环境中存在局限,而std::optional无法携带错误原因。std::expected弥补了这一空白,其核心优势包括:
  • 显式表达操作可能失败,强制调用者处理错误路径
  • 避免异常开销,适用于嵌入式或高性能场景
  • 支持携带丰富的错误类型而非仅布尔状态

基本用法示例

以下代码展示如何使用std::expected解析整数:
#include <expected>
#include <string>
#include <charconv>

std::expected<int, std::string> parse_int(const std::string& str) {
    try {
        size_t pos;
        int value = std::stoi(str, &pos);
        if (pos != str.size()) {
            return std::unexpected("Extra characters after number");
        }
        return value;
    } catch (const std::exception&) {
        return std::unexpected("Invalid integer format");
    }
}
上述函数返回一个包含整数值或错误消息的expected对象。调用者可通过has_value()检查结果,并使用value()或error()访问具体内容。

与现有类型的对比

特性std::optional异常std::expected
携带错误信息否是(栈 unwind)是(类型安全)
零运行时开销是否是
强制错误处理部分隐式显式

第二章:深入理解std::expected的设计原理与核心机制

2.1 std::expected与传统异常处理的性能对比分析

在现代C++中,std::expected作为错误处理的新范式,相较于传统的异常机制,在性能表现上具有显著优势。异常处理依赖栈展开机制,当异常被抛出时,运行时需遍历调用栈寻找合适的处理器,这一过程开销巨大且不可预测。
性能关键指标对比
  • 正常路径执行速度:无错误时,std::expected仅带来极小的额外开销;
  • 错误处理延迟:异常抛出平均耗时为微秒级,而std::expected通过返回值传递错误,控制在纳秒级;
  • 编译优化友好性:返回值模式更利于内联和常量传播。
std::expected<int, Error> compute_value() {
    if (/* 错误条件 */) 
        return std::unexpected(Error::InvalidInput);
    return 42;
}
该代码通过类型系统显式表达可能的失败,避免了异常的非局部跳转机制,使控制流更加清晰且高效。

2.2 错误类型E的合理设计:从std::error_code到自定义错误枚举

在现代C++错误处理机制中,std::error_code提供了系统级错误的抽象,但业务逻辑错误更适合通过自定义枚举进行表达。
自定义错误枚举的优势
相比std::error_code,强类型枚举能提升可读性与类型安全。例如:
enum class FileError {
    Success = 0,
    NotFound,
    PermissionDenied,
    Corrupted
};
该设计避免了跨错误域的隐式转换,增强编译期检查能力。
与标准库的集成
通过特化std::is_error_condition_enum,可使自定义枚举与std::error_code互操作:
template<>
struct std::is_error_condition_enum<FileError> : true_type {};
此机制允许将领域错误无缝融入现有错误处理流程,实现统一接口下的精细化控制。

2.3 值类型T与错误类型E的语义分离与契约保证

在现代类型系统中,值类型 T 与错误类型 E 的语义分离是构建可靠程序的基础。通过将正常路径与异常路径解耦,可显著提升代码的可读性与安全性。
语义分离的设计原则
该模式要求函数返回值明确区分成功结果与错误信息,避免使用特殊值(如 null 或 -1)表示错误。
type Result[T, E any] struct {
    value T
    err   E
    ok    bool
}

func (r Result[T, E]) IsOk() bool  { return r.ok }
func (r Result[T, E]) Unwrap() T   { return r.value }
func (r Result[T, E]) Error() E    { return r.err }
上述泛型结构体封装了值与错误,ok 标志位确保调用者必须显式处理错误路径,防止意外解包。
契约保证机制
通过编译期检查与不可变设计,保障调用方必须验证状态后才能获取值,从而实现“正确性即默认行为”的编程契约。

2.4 和std::variant、std::optional的异同辨析

核心语义差异
std::optional 表示一个值可能存在或不存在,用于替代指针的“空”语义;而 std::variant 是类型安全的联合体,表示“多种类型之一”。两者均避免了裸指针和异常控制流。
使用场景对比
  • std::optional<T>:适用于函数可能无返回值的情况,如查找操作
  • std::variant<T, U>:适用于多类型返回,如解析不同数据类型

std::optional<int> divide(int a, int b) {
    return b != 0 ? std::optional{a / b} : std::nullopt;
}

std::variant<int, std::string> parse(const std::string& s) {
    if (isdigit(s[0])) return std::stoi(s);
    else return s;
}
上述代码中,optional 处理可能失败的计算,variant 实现类型分支。二者结合可构建更健壮的接口设计。

2.5 深入源码:std::expected的内存布局与无异常保证实现

内存布局设计

std::expected<T, E> 采用联合体(union)结合状态标志位的方式存储 T 或 E,确保内存紧凑。其典型布局如下:

template <typename T, typename E>
class expected {
    union {
        T value_;
        E error_;
    };
    bool has_value_;
};

该设计通过 has_value_ 判断当前激活成员,避免虚函数表开销,实现零成本抽象。

无异常保证的实现机制
  • 构造与析构过程中使用 placement new 精确控制对象生命周期;
  • 所有操作在编译期静态检查异常规范,禁用动态异常抛出;
  • 赋值操作采用“先构造后销毁”策略,保障异常安全。

第三章:实战中的错误传播与组合操作

3.1 使用and_then、or_else实现链式错误处理逻辑

在Rust中,`and_then`与`or_else`是Option和Result类型提供的高阶函数,用于构建链式错误处理流程。它们允许开发者以函数式风格依次处理可能失败的操作。
and_then:成功时继续
`and_then`在值为`Some`或`Ok`时执行闭包,否则短路传播错误。

let result = Some(5)
    .and_then(|x| if x > 0 { Some(x * 2) } else { None });
// 输出:Some(10)
该代码表示仅当原始值有效且满足条件时才继续计算,否则返回`None`。
or_else:失败时恢复
`or_else`在值为`None`或`Err`时调用恢复函数。

let fallback = None.or_else(|| Some(42));
// 输出:Some(42)
它常用于提供默认值或备用逻辑路径,增强程序容错能力。 通过组合这两个方法,可构建清晰、可读的错误传播与恢复链条,避免深层嵌套匹配。

3.2 map与transform在结果转换中的高效应用

在数据处理流程中,`map` 与 `transform` 是实现结果转换的核心操作。它们能够将原始数据流高效地映射为所需结构,广泛应用于ETL流程与响应式编程。
map的基本用法
numbers := []int{1, 2, 3, 4}
squared := make([]int, len(numbers))
for i, v := range numbers {
    squared[i] = v * v // 映射为平方值
}
该代码将切片中的每个元素进行平方运算,体现了 `map` 操作的一对一转换特性,适用于批量数据的同步处理。
transform的灵活转换
  • 支持类型转换:如字符串转整型
  • 可嵌套结构映射:JSON字段重排
  • 结合过滤逻辑:转换前预处理数据
通过组合条件判断与结构重组,`transform` 能应对更复杂的业务场景,提升数据适配能力。

3.3 多层函数调用中错误的透明传递与上下文增强

在复杂的系统调用链中,错误信息若仅简单返回,往往丢失关键上下文。通过封装错误并附加调用栈、参数快照等元数据,可实现透明传递与诊断增强。
错误包装与上下文注入
使用带有堆栈追踪的错误包装机制,能在不中断流程的前提下累积上下文:

type wrappedError struct {
    msg     string
    cause   error
    context map[string]interface{}
}

func (e *wrappedError) Error() string {
    return fmt.Sprintf("%s: %v", e.msg, e.cause)
}

func WithContext(err error, msg string, ctx map[string]interface{}) error {
    return &wrappedError{msg: msg, cause: err, context: ctx}
}
上述代码定义了一个可携带上下文的错误包装类型。每次函数调用层捕获错误后,可通过 WithContext 注入当前操作信息(如用户ID、操作资源),形成链式错误结构,便于最终日志回溯。
调用链中的错误增强策略
  • 每一层只添加必要上下文,避免信息冗余
  • 保持原始错误类型可识别,支持精准恢复处理
  • 结合日志系统输出结构化错误链

第四章:工业级项目中的最佳实践模式

4.1 在API设计中统一返回std::expected的接口规范

在现代C++ API设计中,使用 std::expected<T, E> 可以更精确地表达操作结果:成功时返回值,失败时返回错误信息。相比传统的异常或错误码,它兼具类型安全与显式错误处理优势。
接口一致性设计
统一返回 std::expected 能够使所有接口具备一致的返回模式,调用方始终知道需处理成功与失败两种路径。

std::expected<UserData, Error> fetchUser(int id) {
    if (id <= 0) 
        return std::unexpected(Error::InvalidId);
    auto user = database.query(id);
    if (!user.has_value())
        return std::unexpected(Error::NotFound);
    return user.value();
}
上述代码中,fetchUser 返回包含用户数据或错误类型的预期对象。调用者通过 if (result) 判断是否成功,并使用 .value() 或 .error() 获取具体信息。
错误处理流程标准化
  • 所有函数均返回 std::expected,避免混合使用异常和错误码
  • 错误类型应为可枚举或可比较的自定义类型
  • 文档明确标注可能的错误分支,提升可维护性

4.2 避免常见陷阱:临时对象生命周期与隐式转换问题

在C++中,临时对象的生命周期管理不当常导致悬空引用和未定义行为。尤其当函数返回临时对象并绑定到常量引用时,开发者容易误判其生存周期。
临时对象的析构时机
临时对象通常在完整表达式结束时销毁。若将其地址赋给指针或非常量引用,将引发运行时错误:

const std::string& func() {
    return std::string("temporary"); // 危险:返回临时对象引用
}
上述代码中,std::string("temporary") 在函数返回后立即销毁,引用失效。
隐式转换加剧生命周期风险
编译器允许单参数构造函数进行隐式转换,可能意外创建临时对象:
  • 避免使用非显式的单参数构造函数
  • 使用 explicit 关键字防止意外转换
正确做法是按值返回,并依赖移动语义优化性能,确保资源安全。

4.3 与现有异常系统共存的渐进式迁移策略

在引入新异常处理机制时,需确保与传统 try-catch 模式兼容。通过封装适配层,可将原有异常捕获逻辑桥接到新的响应式流中。
异常适配层设计
采用装饰器模式包装旧有服务接口,统一异常输出结构:

public class ExceptionAdapter {
    public <T> Mono<T> wrap(Callable<T> task) {
        return Mono.fromCallable(task)
                   .onErrorResume(e -> {
                       if (e instanceof LegacyException) 
                           return Mono.error(new BusinessException(e.getMessage()));
                       return Mono.error(e);
                   });
    }
}
上述代码将原始异常按类型映射至新体系,保留堆栈信息的同时实现语义升级。
迁移路径规划
  • 第一阶段:并行运行新旧异常处理器,记录差异日志
  • 第二阶段:逐步替换核心模块,验证异常传播路径
  • 第三阶段:下线废弃捕获逻辑,完成治理闭环

4.4 性能敏感场景下的零成本抽象封装技巧

在高性能系统开发中,抽象常带来运行时开销。通过编译期计算与内联优化,可实现零成本抽象。
泛型与内联结合
利用泛型消除接口调用,配合 inline 提示编译器展开函数:
func InlineMin[T comparable](a, b T) T {
    if a < b {
        return a
    }
    return b
}
该函数在编译期实例化具体类型,避免动态调度,生成直接比较指令。
栈分配与零拷贝
通过指针传递避免值复制,结合逃逸分析驻留栈上:
  • 使用 *struct 替代大结构体传参
  • 避免闭包捕获导致堆分配
  • 预分配对象池复用内存

第五章:未来展望:构建健壮且高效的现代C++错误处理体系

异常安全的资源管理策略
在现代C++中,RAII(Resource Acquisition Is Initialization)依然是确保异常安全的核心机制。通过智能指针和自定义析构逻辑,可自动释放资源,避免泄漏。
  • std::unique_ptr 确保独占资源的自动释放
  • std::shared_ptr 支持共享生命周期管理
  • 自定义 deleter 可封装文件句柄、网络连接等非内存资源清理
使用 std::expected 替代传统错误码
C++23 引入的 std::expected 提供了比 errno 或返回码更清晰的错误语义表达,支持携带错误详情。
// 使用 std::expected 返回计算结果或错误类型
std::expected<double, std::string> divide(double a, double b) {
    if (b == 0.0) {
        return std::unexpected("Division by zero");
    }
    return a / b;
}

// 调用侧显式处理成功与失败路径
auto result = divide(10, 0);
if (!result) {
    std::cerr << "Error: " << result.error() << std::endl;
} else {
    std::cout << "Result: " << result.value() << std::endl;
}
错误分类与层级设计
大型系统中应建立统一的错误类型体系,便于跨模块传递和处理。推荐使用枚举类结合错误上下文包装:
错误类别典型场景处理建议
IOError文件读写失败重试或降级到缓存
NetworkError连接超时触发熔断机制
LogicError参数非法立即终止并记录日志
异步任务中的错误传播
在并发环境下,需通过 std::promise 设置异常,或利用 std::future::wait_for 捕获异步异常,确保错误不被静默吞没。
Qt Design Studio 入门指南:从零开始打造炫酷UI(详细+实用+轻松上手) 本文是Qt Design Studio的详细入门指南,旨在帮助UI设计新手从零开始轻松打造炫酷界面。文章系统介绍了软件的核心概念、安装步骤、主界面解析,并通过创建一个完整的登录界面实例,手把手教学如何拖拽组件、设置属性、添加交互状态与动画。同时,分享了创建自定义组件、管理资源以及提升效率的实用技巧与常见问题解决方案,让读者能够快速上手并应用于实际项目开发。 阅读详情

相关推荐

DIY电子管耳放实战:12AU7+6V6GT组合的电路设计与调试心得

本文详细分享了DIY电子管耳放的实战经验,重点解析了12AU7与6V6GT经典组合的电路设计、元件选型与调试过程。内容涵盖从核心架构设计、关键元件(如输出变压器、耦合电容)的科学选型,到静态工作点设置、负反馈引入及常见噪声问题的排查,旨在帮助音响DIY爱好者和电子管放大器初学者成功打造一台低失真、高信噪比且富有“胆味”的耳机放大器,享受动手制作的乐趣与温暖音质。

weixin_29230805的博客 552

C++23 std::expected 详解:告别传统错误码和异常,构建现代健壮代码

C++23引入的std::expected<T,E>为错误处理提供了新范式,通过可区分联合体将成功结果(T)与错误值(E)封装为单一返回值。相较于传统错误码和异常机制,它强制调用者显式检查状态,避免错误被忽略。文章给出了两种C++17兼容实现方案:基于std::variant的完整实现(支持void特化)和简单值+错误码封装版。核心优势包括统一返回路径、语义化判空和保留错误上下文,是替代异常和错误码引用的现代C++最佳实践。

猫哥 的沉淀、积累、总结。天天学习,好好向上...c/c++,嵌入式 linux,Android,HarmonyOS,AIOT) 815

QT6与QT5安装全攻略:从下载到环境配置一站式指南

本文提供了一份详尽的QT6与QT5安装教程,涵盖从版本选择、在线安装器使用到环境变量配置的全过程。针对新手常见痛点,重点对比了QT6与QT5的安装差异,并给出了MinGW与MSVC编译器的选择建议,旨在帮助开发者快速搭建稳定可用的QT开发环境,避免常见错误。

weixin_29216353的博客 311

C++23中的std::expected:异常处理

C++23引入的std::expected为错误处理提供了更优雅的解决方案。这个模板类允许函数返回期望值或错误值,避免了异常处理的复杂性。示例展示了如何使用std::expected处理除零错误:当除数为0时返回错误信息,否则返回计算结果。代码还演示了链式调用,通过and_then和or_else方法进行连续操作。相比传统的异常处理,std::expected提供了更类型安全、更直观的错误处理方式,使代码更加清晰易读。该特性特别适用于需要明确处理错误场景的场合,如数值计算、文件操作等。

ccf19881030的专栏 1260

[漏洞利用]利用五次Shift越权破解win7\win10开机密码

注:第一个学习和接触的Windows漏洞 文章目录本机实验环境前置知识漏洞原理漏洞介绍漏洞验证解决方法基本流程介绍详细步骤截图 本机实验环境 虚拟机:VMware Workstation 14 pro 操作系统:Windows10 前置知识 1、cmd工具路径 c:\windows\system32\cmd,按五次shift默认调用同目录下sethc文件,其路径为“c:\windows\system32\sethc.exe” 2、用户/账户密码存储位置 c:\windows\system32\config\

Y4tacker的博客 2万+

Excel下拉公式不自动计算?5步彻底解决!

Excel下拉公式不自动计算?5步彻底解决!在使用Excel处理数据时,公式下拉填充是提升效率的核心操作。但许多用户都遇到过这样的困惑:明明设置了公式,下拉时结果却纹丝不动。本文将从技术原理出发,结合5步实操方案,为您彻底解析这个高频问题的根源与解决方案。

mmoo_python的博客 1万+

std::expected vs 异常:C++23时代谁才是错误处理的终极答案?

掌握C++23新特性std::expected在错误处理中的最佳实践,提升代码健壮性与性能。对比异常机制,解析适用场景、链式调用与错误传播等核心方法,显著降低运行开销。无异常开销、类型安全明确,现代C++错误处理新标准,值得收藏。

CompiLume的博客 998

UFS逻辑单元管理

介绍UFS 逻辑单元管理和配置

m0_51720747的博客 1947

C++23新特性深度解析(std::expected实战指南):告别传统错误码与异常开销

掌握C++23新特性std::expected错误处理,高效替代传统错误码与异常开销。适用于系统调用、库函数等场景,通过类型安全的预期值设计提升代码健壮性与性能。实战指南助你快速上手,值得收藏。

ByteVein的博客 1052

5分钟搞定Vivado IP核的VCS仿真:从Export脚本到Verdi波形查看全流程

本文详细介绍了如何利用Vivado的Export Simulation功能,快速搭建Vivado IP核的VCS与Verdi联合仿真环境。通过自动化脚本生成、FSDB波形配置及高效调试技巧,实现从工程导出到波形查看的全流程,大幅提升FPGA验证效率,尤其适合IC验证工程师和竞赛团队。

weixin_29306261的博客 482

Gromacs基础教程一:入门建议

本系列教程针对的群体:非计算化学专业,而是偏生物方向的、有少量分子动力学模拟需求的人群。

m0_67843839的博客 8574

【C++23错误处理革命】:std::expected如何重塑现代C++异常安全设计

掌握C++23新特性std::expected错误处理,提升代码异常安全性。通过返回值替代异常,避免开销,适用于网络请求、文件操作等场景,实现清晰高效的错误传递机制。现代C++错误处理的首选方案,值得收藏。

PixelShoal的博客 626

LDRA Testbed(TBrun)软件单元测试_操作指南

通过前面的几篇文章,使用Testbed进行软件静态分析的内容已经基本讲解完毕。从这篇文章开始,将继续讲解如何使用TBrun进行软件单元测试、软件集成测试。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 7771

C++23 std::expected:一种新的词汇表类型,用于返回函数的结果

主模板:在其自身的存储空间内包含期望值或非期望值,该存储空间嵌套在expected对象内。void部分特化:表示期望的void值或包含非期望值。如果它包含非期望值,则它嵌套在expected对象内。C++23引入的为函数返回结果的处理提供了一种更加优雅、类型安全的解决方案。它解决了传统错误处理方法的一些痛点,如类型安全问题、代码可读性问题和性能开销问题等。通过使用,开发者可以编写出更加健壮、可维护的代码。在实际开发中,建议开发者积极采用。

码事漫谈 1928

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C++23 std::expected深度剖析:构建零成本错误处理架构的秘诀

掌握C++23新特性std::expected在错误处理中的最佳实践,构建高效零成本异常替代方案。适用于系统级编程与高可靠性场景,结合模式匹配与链式调用提升代码健壮性。清晰语义与无性能开销兼得,值得收藏。

VarFlow的博客 994

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

(std::expected完全手册):C++23中不容错过的错误处理利器

掌握C++23新特性std::expected在错误处理中的最佳实践,提升代码健壮性与可读性。适用于函数返回多状态场景,替代异常和错误码,实现无开销的类型安全错误传递。结合模式匹配与链式调用,简化错误处理逻辑,值得收藏。

LearnFlow的博客 888

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C++23 std::expected实战指南(错误处理新范式大揭秘)

掌握C++23新特性std::expected在错误处理中的最佳实践,提升代码健壮性与可读性。本文详解其在函数返回值、异常替代场景的应用,对比传统错误码与异常机制,突出类型安全与性能优势,帮助开发者优雅处理错误流程,值得收藏。

ProceGlow的博客 759

为什么Google、Microsoft都在用std::expected?深入剖析C++23错误处理新标准

掌握C++23新特性std::expected在错误处理中的最佳实践,有效替代异常与错误码,提升代码健壮性与可读性。适用于系统调用、库函数等场景,实现零成本错误传递与链式操作,值得收藏。

ProceSeed的博客 1012

【C++20/23进阶必学】:掌握std::expected,写出更安全、更高效的代码

掌握C++23新特性std::expected错误处理,提升代码安全与性能。适用于函数返回值场景,替代异常和错误码,实现无开销的预期结果与错误分离设计。语义清晰、异常安全,是现代C++健壮编程的关键实践,值得收藏。

VarFlow的博客 1035

揭秘C++23 std::expected:如何用它写出更安全、高效的错误处理代码?

掌握C++23新特性std::expected在错误处理中的最佳实践,提升代码安全与性能。适用于函数返回异常场景,避免异常开销,增强可读性与错误传播效率。结合模式匹配与链式调用,显著优化错误处理逻辑,值得收藏。

FastProceed的博客 754

揭秘C++23 std::expected:如何用类型安全替代异常实现高效错误处理

掌握C++23新特性std::expected在错误处理中的最佳实践,有效替代异常实现类型安全的高效错误传递。适用于系统调用、资源管理等场景,结合模式匹配与函数式风格提升代码健壮性,减少运行时开销,值得收藏。

CompiGlow的博客 676

C++23中std::optional和std::expected的单子式操作

C++23中为和引入的单子式操作(transform、or_else与and_then)为C++编程带来了更强大的功能和更简洁的代码风格。这些操作借鉴了函数式编程的思想,使得我们可以更方便地处理可选值和错误情况,避免了大量的手动错误检查和嵌套的if-else语句,提高了代码的可读性和可维护性。在实际开发中,合理使用这些操作可以让我们的代码更加健壮和优雅。

码事漫谈 942

从Result到std::expected,现代C++错误处理演进之路,你跟上了吗?

掌握C++23新特性std::expected在错误处理中的最佳实践,提升代码健壮性与可读性。适用于函数返回多状态场景,替代异常与传统Result模式,实现零成本错误传递。结合模式匹配与链式调用,简化错误处理逻辑,值得收藏。

InstrWander的博客 965

C++23 std::expected完全指南:5个关键使用场景让你避开90%的错误陷阱

掌握C++23新特性std::expected错误处理,有效替代异常与错误码。涵盖函数返回、链式调用、自定义错误类型等5大场景,提升代码安全与可读性。避免常见陷阱,写出更健壮的C++程序,值得收藏。

LiteCompile的博客 1008
上一篇: 混合编程必看!,Java调用Kotlin挂起函数的4种方式及性能对比(Coroutines 1.8实测)
下一篇: C#开发者必看的Blazor Hybrid进阶技巧(.NET MAUI 9.0深度整合方案)
QuickProceed
博客等级 码龄1年 149粉丝 2008原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值