递增迭代器超出范围
Incrementing iterator out of range
递增随机访问迭代器超出范围是否违法?事实证明,矢量的Visual C++实现触发了调试断言。
std::vector<int> foo(5);
auto iter = foo.begin();
iter += 10;
只要没有评估内存位置,这对于指针来说应该是合法的。
编辑:显然,即使有指针,这也是非法的。
这是未定义的行为。两者都带有迭代器和指针。具有迭代器,您可能会得到断言失败,至少在迭代器调试已打开。有了指针,它可能会在大多数现代建筑中什么都没有,但已经有了机器它可以在陷阱中触发。你不必访问内存位置本身,只需创建指针,用于未定义的行为发生
编辑:
根据标准(§5.7/5,增加了括号):
当具有整型的表达式被添加到或从中减去时指针,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向从原始元素,使得所得数组元素和原始数组元素等于积分表达式。在里面换句话说,如果表达式P指向数组的第i个元素对象,表达式(P)+N(等价地,N+(P))和(P)-N(其中N值n)分别指向第i+n个和第i−n个数组对象的元素,前提是它们存在。此外,如果表达式P指向数组对象的最后一个元素表达式(P)+1指向数组对象的最后一个元素之后的一个,并且如果表达式Q指向数组的最后一个元素之后的一个对象,表达式(Q)-1指向数组的最后一个元素对象如果指针操作数和结果都指向相同的阵列对象或经过阵列对象的最后一个元素的一个,评估不得产生溢出;否则,行为未定义。
随机访问迭代器的相应规则(只有支持添加)分布在几个部分:+=
运算符根据重复的++
定义(对于语义,它是需要具有恒定的时间复杂度),并且++
具有该要求";pre:r是不可引用的。post:r不可引用或r已经过了终点”(来自输入迭代器的定义由前向迭代器继承,后者由双向继承由随机访问迭代器继承的迭代器)。
这是未定义的行为,意味着任何事情都可能发生,包括segfault,或您所经历的,或其他任何事情。基本上,你只是幸运的是它没有坠毁(或者说不幸运,基于观点)。
该语言不需要检查迭代器访问,因为这需要运行时检查。C++通常试图避免不必要的运行时开销,让程序员执行任何必要的检查。
大多数现代平台使用分页虚拟内存,提供粒度为几千字节的内存保护。这意味着在分配的块(例如std::vector管理的块)之后通常有可访问的内存,在这种情况下,超出范围的访问只会践踏该内存。
Visual Studio正试图帮助删除危险代码。原则上,如果不取消引用,指针可以指向任何地方,但迭代器是一种更高级别的抽象,能够检测取消引用是否有效,从而引发运行时错误。Visual Studio至少从VS2007开始就在vector<T>::iterator
上做到了这一点。
- 转到基于范围的 for 循环中的下一个迭代器
- C++:返回一个基于范围 for 循环迭代器,其中包含继承对象
- 迭代器范围的平衡分区,没有LegacyRandomAccessIterator
- 为什么范围算法与 std 的迭代器不兼容?
- Deque 迭代器超出范围
- unordered_set范围插入与迭代器
- 类型不可知的抽象以使用相同的运行时接口处理正向和反向迭代器和范围?
- 访问基于范围的循环(如for_each)中的std::map迭代器
- 迭代器的范围 TS 和 C++20 概念是否需要能够使用"运算符>"?
- 列出超出范围的擦除迭代器
- 如何使用提升范围将自定义迭代器封装在函数中
- 无法取消引用超出范围的向量迭代器 - 有什么问题?
- 如何在基于范围的 for 循环中更改(向前/向后移动)迭代器?
- 如何修复错误,迭代器未在此范围内声明,并且迭代器未命名类型'
- 将迭代器放置为临时范围时,非销钉 - 操作和错误
- C 迭代器范围使用指针到数组
- 为什么我们要把 :: (范围重新定位运算符)放在迭代器之前
- 将迭代器范围复制到矢量而不重复
- C++:指向错误元素的提升范围迭代器
- re C++范围迭代器:只有一个类不好吗