c++ - std::Optional 怎么永远不会 "valueless by exception"?

标签 c++ c++17 stdoptional std-variant

std::variant 可以进入名为“valueless by exception ”的状态。

据我了解,造成这种情况的常见原因是移动分配抛出异常。变体的旧值不再保证存在,预期的新值也不再存在。

然而,

std::Optional 没有这样的状态。 cppreference 做出了大胆的声明:

If an exception is thrown, the initialization state of *this ... is unchanged, i.e. if the object contained a value, it still contains a value, and the other way round.

std::Optional 如何能够避免变得“因异常而毫无值(value)”,而 std::variant 却不能?

最佳答案

optional<T>有两种状态之一:

  • 一个T

一个variant如果转换会抛出异常,则只能在从一种状态转换到另一种状态时进入无值(value)状态 - 因为您需要以某种方式恢复原始对象,并且执行此操作的各种策略需要额外的存储1、堆分配< support>2,或空状态3

但是对于 optional ,从 T 过渡空虚只是一种破坏。所以只有 T 才会抛出异常的析构函数抛出,此时谁在乎呢。并从空过渡到 T不是问题 - 如果抛出异常,很容易恢复原始对象:空状态是空的。

具有挑战性的案例是:emplace()当我们已经有了 T 。我们必然需要销毁原始对象,那么如果 emplace 构造抛出异常我们该怎么办?与optional ,我们有一个已知的、方便的空状态可以回退 - 所以设计就是为了做到这一点。

variant问题在于没有那么容易恢复到的状态。

<小时/>

1 作为 boost::variant2 确实如此。
2 作为 boost::variant 确实如此。
3 我不确定执行此操作的变体实现,但有一个设计建议 variant<monostate, A, B>可以转换为 monostate说明它是否持有 A以及过渡到 B扔了。

关于c++ - std::Optional 怎么永远不会 "valueless by exception"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57696187/

相关文章:

c++ - 从 DLL 函数调用非 DLL 函数

c++ - glVertex3f 和 glVertex2fx 显示不同的结果

c++ - 使用较小的默认对齐方式重载 operator new

c++ - 基于无辜范围的 for 循环不起作用

c++ - 如何在 Xcode 中获得 std::optional 支持?

c++ - 查找启动进程的命令行选项

c++ - 如何在命令行上使用 Qt 进行是/否对话?

c++ - 折叠表达式是否会短路?

c++ - std::optional<>::emplace() 是否会使对内部值的引用无效?

c++ - boost 是否有一个 "compact optional",其中存在由类型的特殊值编码?