std::variant
可以进入一种称为“valueless by exception”的状态。
据我所知,这种情况的常见原因是移动赋值引发异常。变体(variant)的旧值不再保证存在,预期的新值也不再存在。
std::optional
则没有这种状态。cppreference对此做出了大胆声明:
如果引发异常,则*this的初始化状态…保持不变,即如果对象包含一个值,则仍然包含一个值,反之亦然。
std::optional
如何避免变成“valueless by exception”,而std::variant
没有呢?
optional<T>
从T
转换到另一个T
状态的情况。请注意,在过程中如果抛出异常,emplace
和operator=
的行为是不同的! - Max Langhofemplace
中的构造函数抛出异常,那么将显式声明optional
未参与。如果operator=
在构造期间抛出异常,那么同样没有值。Barry的观点仍然有效:它之所以有效是因为始终存在一个合法的空状态,可以将optional
设置为空。variant
没有这种奢侈,因为variant
不能为空。 - Nicol BolasT::operator=
- 这种特定情况不涉及空的optional
或者任何析构函数。由于此答案中涉及std::optional
的所有案例都涉及销毁或者空状态,因此我认为这个重要案例(其他答案都没有涉及)被遗漏了。别误会,这个答案完全涵盖了其他所有方面,但我自己还必须阅读这个最后一个案例... - Max Langhof**this = *other
的事情。 - L. F.std::variant
(或std::optional::emplace
)一样破坏并重新创建包含的实例。但我认为这取决于人们认为哪些规范部分是显而易见的,以及什么需要解释。这里的答案在这方面有所不同,它应该涵盖接口可能存在的不同预设。 - Max Langhof