vla*_*don 2 c++ segmentation-fault language-lawyer c++17 stdoptional
这个例子:
#include <optional>
#include <iostream>
using namespace std;
int main()
{
optional<int> t{}; // nullopt (empty) by default
cout << *t << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
实际上这个程序打印一些int(未初始化的类型值int).此外,libcxx使用assert-check来访问非参与值.
为什么标准不要求扔或sigsegv在这里?
eer*_*ika 10
为什么标准不要求扔或sigsegv在这里?
因为要求某些特定行为隐含地强制要求添加分支以检查是否应该发生该行为 - 无论是抛出还是其他行为.
通过指定行为未定义,标准允许实现不检查每个间接时可选是否为空.分支执行可能比不分支更慢.
委员会不是强制要求安全,而是让标准库实施者选择性能(和简单性).您测试的实现似乎选择不抛出异常或以其他方式通知您错误.
C++包含未定义行为的概念.
并非所有C++操作都具有标准定义的行为.这允许编译器假设它们永远不会发生,并且在许多情况下可以导致更快的代码.
这里,通过保留std::optional未定义的未使用的结果,访问存储在a std::optional中的数据的成本与访问未存储在a中的数据的成本相同std::optional.唯一的成本是需要额外的空间,而你作为程序员承诺跟踪是否参与.
现在编译器可以在那里插入检查,有些则在调试版本中.
请注意,通常C++ std库类型包括访问数据的安全和不安全方法.
无效指针有时会导致sigsev的事实是因为大多数操作系统保护地址大约为0并且崩溃访问它的程序.这是因为这是一个低成本,它从许多汇编,C和C++程序中捕获了一堆不良行为.
如果你想在空时抛出可选项,请使用.value().如果不这样做,请使用operator*.如果您想要一个默认值,如果不存在,请使用.value_or.
因为它是未定义的行为,所以[optional.observe] p5部分说:
要求:*这包含一个值.
并且违反了一个require子句是未定义的行为,来自[res.on.required#1] p1,这是在图书馆范围内的要求:
违反函数的Requires:元素中指定的任何前提条件会导致未定义的行为,除非函数的Throws:元素指定在违反前提条件时抛出异常.
所以你没有关于结果的预期.从未定义行为的定义:
本文档没有要求的行为
要求实施检查将是一项成本,并非所有用户都希望获得该成本.因此,这成为一个实施质量问题.实现可以在不同的操作模式下执行检查,例如在启用断言时.
用户可以选择通过has_value或value_or自行获取成本.如果用户想要可以抛出的操作,他们可以使用值.
请注意,sigsegv,segfaults等...是一个实现定义的行为.
| 归档时间: |
|
| 查看次数: |
183 次 |
| 最近记录: |