为什么STL中允许未定义的行为
Why is undefined behavior allowed in the STL?
默认情况下,std::stack
的"底层容器"是std::deque
。因此,对于std::deque
而言,任何未定义的行为都是对于std::stack
而言的未定义行为。cppreference和其他站点在描述成员函数的行为时使用术语"有效"。我认为这意味着它是为了所有的意图和目的。因此,调用top()
和pop()
等同于调用back()
和pop_back()
,在空容器上调用它们是未定义的行为。
根据我的理解,它之所以是未定义的行为,是为了保留无投掷保证。我的推理是,std::vector
的operator[]
有无抛出保证,如果容器大小大于N,则是未定义的行为,但at()
有强保证,如果N超出界限,则抛出std::out_of_range
。
所以我的问题是,有些事情可能有未定义的行为,并有一个不抛出保证,而有一个强有力的保证,但却抛出了一个异常,这背后的理由是什么?
当允许未定义的行为时,出于效率的原因,通常是。
如果标准指定了访问越界数组时必须执行的操作,则会强制实现检查索引是否在边界内。向量也是如此,它只是一个动态数组的包装器。
在其他情况下,允许对行为进行未定义,以便在实施中允许自由。但这也关乎效率(因为一些可能的实现策略在某些机器上可能比在其他机器上更高效,而C++则让实现者自己选择最高效的策略,如果他们愿意的话。)
根据Herb Sutter的说法,一个明显的原因是效率。他指出,该标准没有对operator[]
的异常规范或是否需要绑定检查提出任何要求。这取决于实施。
另一方面,允许
vector<T>::operator[]()
,但不允许必需,以执行边界检查。一点措辞都没有在operator[]()
的标准规范中关于边界检查,但也没有任何要求有一个异常规范,所以您的标准库实现程序也可以自由地向operator[]()
添加边界检查。所以,如果你使用operator[]()
要求一个不在向量中的元素而标准并不能保证发生(尽管您的标准库实现的文档may)--您的程序可能会立即崩溃,调用operator[]()
可能会抛出异常,或者事情似乎正常偶尔和/或神秘地失败。考虑到边界检查保护我们免受许多常见问题的影响,为什么
operator[]()
不需要执行边界检查?这个简短的回答是:效率。总是检查边界会导致所有程序的性能开销(可能很小),即使是那些永远不要越界。C++的精神包括这样一句格言:总的来说,你不应该为你不使用的东西付费,所以operator[]()
不需要边界检查。在这种情况下,我们有一个额外的理由想要效率:矢量是有意的使用,而不是内置数组,因此应该同样高效作为内置数组,不进行边界检查。如果你想成为确保检查了边界,请改用at()
。
如果您对性能优势感到好奇,请参阅以下两个问题:
- ::std::vector::at()vs运算符[]<lt;令人惊讶的结果!!速度慢5到10倍/更快
- vector::at与vector:,运算符[]
人们一致认为operator[]
更高效(因为std::vector
只是动态数组的包装器,所以operator[]
应该和在数组上调用它一样高效。)Herb Sutter似乎认为它是否是异常安全的取决于编译器供应商。
- 编译C++时未定义的引用
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 未定义的引用在哪里
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 对Py_Initialize()的未定义引用
- c++11评估顺序(未定义的行为)
- 使用mysql c++连接器的未定义引用
- 从python调用openMP共享库时,未定义opnMP函数
- 使用向量(STL)时,未定义的行为,请说明理性背后的以下代码输出
- 为什么STL中允许未定义的行为
- 从 STL 容器继承并删除"新"运算符以防止由于缺少虚拟析构函数而导致未定义的行为是否有意义?
- 为什么STL实现不使用断言来检测未定义的行为
- const_cast const STL 容器,它是未定义的行为
- STL Vector:临时调用 data() 时的未定义行为
- c++ 11 STL列表=和!= op未定义
- 有状态函子和STL:未定义的行为