示例:
#include <optional>
#include <iostream>
using namespace std;
int main()
{
optional<int> t{}; // nullopt (empty) by default
cout << *t << endl;
return 0;
}
实际上,该程序输出一些int(类型为int
的未初始化值)。
另外,libcxx使用assert-check来访问未使用的值。
为什么标准不需要在此处抛出或sigsegv?
答案 0 :(得分:10)
为什么标准不需要在此处抛出或sigsegv?
由于需要某种特定的行为,因此暗含了添加一个分支来检查该行为(无论是抛出行为还是其他行为)的要求。
通过指定行为是未定义的,该标准允许实现 not 检查每个间接引用中的optional是否为空。分支执行可能比不分支慢。
委员会没有强制安全性,而是让标准库实施者选择性能(和简便性)。您测试的实现似乎选择了不引发异常或以其他方式通知您错误。
答案 1 :(得分:8)
C ++包含未定义行为的概念。
并非所有C ++操作都具有标准定义的行为。这使编译器可以假定它们永远不会发生,并且在许多情况下可以使代码更快。
在这里,通过保留未定义的std::optional
的使用结果,访问std::optional
中存储的数据的开销与访问{}中没有存储的数据的开销相同{1}}。唯一的成本就是所需的额外空间,而作为程序员的您将保证跟踪是否参与其中。
现在,编译器可以自由地在其中插入检查,有些可以在调试版本中进行。
请注意,通常C ++ std::optional
库类型包括用于访问数据的 safe 和 unsafe 方法。
无效指针有时会导致sigsev的事实是因为大多数操作系统的保护地址都在0左右,并且崩溃了访问该地址的程序。这是因为这是低成本,并且从许多汇编,C和C ++程序中捕获了许多不良行为。
如果要让可选内容在空时抛出,请使用std
。否则,请使用.value()
。如果您不希望使用默认值,请使用operator*
。
答案 2 :(得分:6)
由于这是未定义的行为,因此第[optional.observe]p5节说:
要求:*其中包含一个值。
违反require子句是未定义的行为,来自[res.on.required#1]p1下的 Library-wide requirements:
违反函数的Requires:元素中指定的任何前提条件会导致未定义的行为,除非函数的Throws:元素指定在违反前提条件时抛出异常。
因此您对结果没有期望。根据{{3}}的定义:
本文档不要求其行为的行为
要求执行检查是一项费用,并非所有用户都希望承担该费用。因此,这成为实施质量的问题。实现可以自由地在不同的操作模式下执行检查,例如,在启用断言时。
用户可以选择通过undefined behavior或has_value自行承担费用。如果用户希望进行可以抛出的操作,则可以使用value_or。
请注意,value。