std ::推进超出容器结束时的行为

Rai*_*dog 24 c++ stl

当你说:std :: advance的行为是什么时候:

std::vector<int> foo(10,10);
auto i = foo.begin();
std::advance(i, 20);
Run Code Online (Sandbox Code Playgroud)

什么是价值?是foo.end()

Mic*_*urr 31

该标准std::advance()根据它所使用的迭代器类型(24.3.4"迭代器操作")定义:

这些函数模板使用+和 - 用于随机访问迭代器(因此,它们是恒定的时间); 对于输入,转发和双向迭代器,它们使用++来提供线性时间实现.

各种迭代器类型的这些操作的要求也在标准中列出(表72,74,75和76):

因此,将迭代器推进到"过去 - 结束"值之外(可能由end()容器上的函数返回)或者在迭代器的有效范围的第一个可解除引用的元素之前前进(可能由begin()容器返回)是未定义的行为因为你违反了++--操作的先决条件.

由于它是未定义的行为,你无法"期待"任何特别的东西.但是你可能会在某些时候崩溃(希望更早而不是更晚,所以你可以修复这个bug).


Kir*_*sky 7

根据C++标准§24.3.4 std::advance(i, 20)具有与for ( int n=0; n < 20; ++n ) ++i;积极相同的效果n.从另一方面(第24.1.3节),如果i是过去,则++i操作未定义.所以结果std::advance(i, 20)是未定义的.


Mah*_*esh 3

您已foo晋级到第 20 位,从而超越了规模。绝对不是向量的结尾。据我所知,它应该在取消引用时调用未定义的行为

编辑1:

#include <algorithm>
#include <vector>
#include <iostream>

int main()
{
     std::vector<int> foo(10,10) ;
     std::vector<int>::iterator iter = foo.begin() ;
     std::advance(iter,20);

     std::cout << *iter << "\n" ;

     return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出: 0

如果它是向量的最后一个元素,那么它应该在迭代器解引用时给出 10。所以,是UB。

IdeOne 结果

  • 你的例子不正确。即使迭代器被限制到“end()”,它仍然不会指向任何有效的东西。 (6认同)
  • 马克的观点是,前进到向量的最后一个元素是明确定义的(尽管您不能取消引用该迭代器)。换句话说,使用您的示例,如果“advance”行是:“std::advance(iter,10)”,则此时不会有 UB,尽管执行“cout”表达式时会出现 UB 。因此,如果当迭代器到达该点时,将“advance()”指定为以某种方式“粘在”“end()”上,则您的示例仍将显示 UB,但不会在调用“advance()”时显示。 (3认同)