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()
的调用。