C++ std::前进超过容器末端时的前进行为

C++ std::前进超过容器末端时的前进行为,c++,stl,C++,Stl,当你说: std::vector<int> foo(10,10); auto i = foo.begin(); std::advance(i, 20); std::vectorfoo(10,10); 自动i=foo.begin(); 标准:预付款(i,20); i的值是多少?是不是foo.end()?您前进到第20位,通过了foo大小。这肯定不是向量的终点。它应该在取消引用时调用未定义的行为,AFAIK 编辑1: #include <algorithm> #inclu

当你说:

std::vector<int> foo(10,10);
auto i = foo.begin();
std::advance(i, 20);
std::vectorfoo(10,10);
自动i=foo.begin();
标准:预付款(i,20);

i的值是多少?是不是foo.end()

您前进到第20位,通过了
foo
大小。这肯定不是向量的终点。它应该在取消引用时调用未定义的行为,AFAIK

编辑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;
}
#从SGI页面包括以下内容:

i和i+n之间的每个迭代器 (包括)是非奇异的

因此,我不是foo.end(),取消引用将导致未定义的行为

注:

  • 有关引用迭代器时(非)单数的含义的更多详细信息,请参阅
  • 我知道SGI页面不是事实上的标准,但几乎所有STL实现都遵循这些准则

  • 这可能是未定义的行为。该标准唯一规定的是:

    由于只有随机访问迭代器提供+和-运算符,因此该库提供了两个函数模板advance和distance。这些函数模板使用+和-表示随机访问迭代器(因此,它们的时间是恒定的);对于输入、正向和双向迭代器,它们使用++提供线性时间实现

    template <class InputIterator, class Distance> 
    void advance(InputIterator& i, Distance n);
    
    模板
    无效提前(输入和输入,距离n);
    

    要求:n应仅对双向和随机访问迭代器为负。作用:增量(或负n)迭代器引用i由N.< /P> < P>根据C++标准“24.3.4<代码> STD::前进(I,20)具有与<代码>相同的效果(int n=0;n<20;++n)++i;<代码>为正
    n
    。从另一侧(§24.1.3)看,如果
    i
    已过终点,则
    ++i
    操作未定义。因此,
    std::advance(i,20)
    的结果是未定义的。

    标准根据其所使用的迭代器类型(24.3.4“迭代器操作”)定义了
    std::advance()

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

    标准中还概述了对各种迭代器类型的这些操作的要求(表72、74、75和76):

    • 对于输入或前向迭代器

      ++r precondition: r is dereferenceable
      
    • 对于双向迭代器:

      --r precondition: there exists s such that r == ++s
      
    • 对于随机访问迭代器,
      +
      +=
      -
      -=
      操作是根据双向和正向迭代器前缀
      +
      -
      操作定义的,因此相同的前提条件成立

    因此,将迭代器前进到“超过结束”值(可能由容器上的
    end()
    函数返回)之前,或前进到迭代器有效范围的第一个可取消引用元素之前(可能由容器上的
    begin()
    返回)是未定义的行为,因为您违反了
    ++
    --
    操作的前提条件


    因为它是未定义的行为,所以你不能“期待”任何特别的东西。但是您可能会在某个时候崩溃(希望是更早,而不是更晚,这样您就可以修复错误)。

    您的示例不正确。即使迭代器被钳制在
    end()
    上,它仍然不会指向任何有效的对象。@标记Ransom-相反,我应该说向量中的最后一个元素。修改了术语并感谢您的通知。Mark的观点是,前进到刚好超过向量的最后一个元素是定义良好的(尽管您不能取消对该迭代器的引用)。换句话说,使用您的示例,如果
    advance
    行是:
    std::advance(iter,10)
    ,那么在该点上不会有UB,尽管执行
    cout
    表达式时会有UB。因此,如果在迭代器到达该点时,
    advance()
    被指定为以某种方式“坚持”在
    end()
    上,那么您的示例仍然会显示UB,但不会显示对
    advance()
    的调用。