增加迭代器超出范围

时间:2015-02-09 11:26:54

标签: c++

将随机访问迭代器增加到超出范围是不合法的吗? 事实证明,Vector的C ++实现触发了调试断言。

std::vector<int> foo(5);
auto iter = foo.begin();
iter += 10;

只要未评估内存位置,这对于指针应该是合法的。

编辑:显然即使使用指针也是非法的。

2 个答案:

答案 0 :(得分:4)

这是未定义的行为。两者都有迭代器和指针。同 迭代器,你可能会得到一个断言失败,至少是 迭代器调试已打开。有了指针,它可能会做 在大多数现代建筑中都没有,但是已经有了机器 它可以在陷阱中触发。您不必访问内存 位置本身,只是创建指针,用于未定义的行为 发生。

编辑:

从标准(§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是dereferenceable或r 是过去的结束。“(从输入迭代器的定义,其中 由前向迭代器继承,它由双向继承 迭代器,由随机访问迭代器继承。)

答案 1 :(得分:3)

这是未定义的行为,这意味着任何事情都可能发生,包括段错误,或您经历过的事情或其他任何事情。基本上,你很幸运它没有崩溃(或根据观点不幸)。

该语言不需要检查迭代器访问,因为这需要运行时检查。 C ++通常会尝试避免不必要的运行时开销,让程序员执行任何必要的检查。

大多数现代平台使用分页虚拟内存,提供几千字节的内存保护。这意味着在分配的块(例如由std :: vector管理的块)之后通常存在可访问的内存,在这种情况下,超出范围的访问将只是踩踏该内存。

Visual Studio正试图帮助删除危险代码。原则上,如果您没有取消引用它,指针可以指向任何位置,但迭代器是更高级别的抽象,并且能够检测取消引用是否有效并因此引发运行时错误。至少从VS 2007开始,Visual Studio已经使用vector<T>::iterator完成了这项工作。