现代 C++ 编程实战
吴咏炜
前 Intel 资深软件架构师
34196 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
加餐 (1讲)
现代 C++ 编程实战
15
15
1.0x
00:00/00:00
登录|注册

22 | 处理数据类型变化和错误:optional、variant、expected和Herbception

Herbception的基本语法
expected的基本用法
expected模板
variant的成员函数
替代带标签的联合的数据结构
variant类型
optional的高阶函数
optional对象的操作
构造optional<T>对象的方法
C++17引入的optional模板
Niall Douglas, “P1028R0: SG14 status_code and standard error object for P0709 Zero-overhead deterministic exceptions”
Herb Sutter, “P0709R0: Zero-overhead deterministic exceptions: Throwing values”
Simon Brand, expected
Vicente J. Botet Escribá and JF Bastien, “Utility class to represent expected object”
Andrei Alexandrescu, “Systematic error handling in C++”
cppreference.com, “std::visit”
cppreference.com, “std::variant”
Chase Geigle, cpptoml
cppreference.com, “std::optional”
Wikipedia, “Null object pattern”
Herbception
expected
variant
optional
C++异常处理方式
参考资料
课后思考
内容小结
其他结构适用于错误处理
异常处理
C++错误处理方式

该思维导图由 AI 生成,仅供参考

你好,我是吴咏炜。
我们之前已经讨论了异常是推荐的 C++ 错误处理方式。不过,C++ 里有另外一些结构也很适合进行错误处理,今天我们就来讨论一下。

optional

在面向对象(引用语义)的语言里,我们有时候会使用空值 null 表示没有找到需要的对象。也有人推荐使用一个特殊的空对象,来避免空值带来的一些问题 [1]。可不管是空值,还是空对象,对于一个返回普通对象(值语义)的 C++ 函数都是不适用的——空值和空对象只能用在返回引用 / 指针的场合,一般情况下需要堆内存分配,在 C++ 里会引致额外的开销。
C++17 引入的 optional 模板 [2] 可以(部分)解决这个问题。语义上来说,optional 代表一个“也许有效”“可选”的对象。语法上来说,一个 optional 对象有点像一个指针,但它所管理的对象是直接放在 optional 里的,没有额外的内存分配。
构造一个 optional<T> 对象有以下几种方法:
不传递任何参数,或者使用特殊参数 std::nullopt(可以和 nullptr 类比),可以构造一个“空”的 optional 对象,里面不包含有效值。
第一个参数是 std::in_place,后面跟构造 T 所需的参数,可以在 optional 对象上直接构造出 T 的有效值。
如果 T 类型支持拷贝构造或者移动构造的话,那在构造 optional<T> 时也可以传递一个 T 的左值或右值来将 T 对象拷贝或移动到 optional 中。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

C++17引入了optional、variant和expected三个模板,它们分别用于处理返回值可能为空、多种类型对象和异常处理。optional代表一个“也许有效”“可选”的对象,可以避免空指针带来的问题。文章介绍了optional的构造方法、标准库支持的操作以及高阶函数lift_optional的使用方法。此外,还介绍了variant和expected的使用方法和特点。其中,Herbception提出了一种基本兼容当前C++异常处理方式的错误处理方式,被戏称为Herbception。虽然语法上基本是使用异常的样子,但Herb的方案却没有异常的不确定开销,性能和使用expected相仿。总的来说,本文介绍了C++17引入的optional模板以及其他相关模板的基本概念和使用方法,为读者提供了对这些模板的快速了解和应用指导。文章内容涵盖了这些模板的基本概念、使用方法以及与异常处理的比较,为读者提供了对这些模板的快速了解和应用指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++ 编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • 廖熊猫
    有的语言里面没有try catch,统一使用类似optional的结局方案,比如Rust里面的Err,Haskell中对应的应该是Either类型,这些都是处理可以恢复的错误,不可恢复的直接就让程序崩了。 lift_optional让我想起来被Haskell支配的恐惧 (Just (+) ) <*> Just 41 <*> Just 1 不知道老师后面会不会讲到monad😂

    作者回复: optional 对应的是 Maybe 吧。expected 比较像 Either。 不会讲 monad。这个即使专门讲函数式编程也要比较后面呢。

    2020-01-15
    2
  • tt
    老师,听了您的课后,觉得现在C++标准提案有很多都是利用C++的语义和语法来写提升编程便利性的模板,是这样么? 还有,一直不知道C++的异常是怎么实现的,还有这里说的异常处理的性能问题,有推荐的比较好阅读的参考文献么?

    作者回复: 是的。提高开发的友好程度,尤其是对新手的友好程度,一直是 C++ 委员会的目标。你应该发现虽然语言越来越复杂,但很多东西却越来越好写了。 异常的实现非常复杂。想了解的话需要花点力气。不过我倒是查到有篇还不错的中文文章,推荐一看: http://baiy.cn/doc/cpp/inside_exception.htm

    2020-01-15
    2
    2
  • Geek_7d9f3b
    C++中是否有关闭异常的方式,实践中经常遇到分配内存时出现了bad_alloc直接让程序terminate掉了,涉及的历史代码又非常多,一个个try catch(...)既耗时又会造成程序性能的下降…

    作者回复: 标准里没有。而且,能关闭异常的编译器,在标准库里碰到内存不足程序一样挂。 关于这个问题的详细讨论,可以参见: https://zhuanlan.zhihu.com/p/617088259

    2023-09-17归属地:广东
    2
  • ×22
    感觉optional就和rust里面的Option<>一样?

    作者回复: 应该是吧。但我对Rust不熟。

    2022-09-27归属地:江苏
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部