当你说: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):
对于输入或转发迭代器
++r precondition: r is dereferenceable
Run Code Online (Sandbox Code Playgroud)对于双向迭代器:
--r precondition: there exists s such that r == ++s
Run Code Online (Sandbox Code Playgroud)对于随机访问迭代器的+,+=,-,和-=操作在双向和前向迭代前缀来定义++和--操作,所以相同的前提条件成立.
因此,将迭代器推进到"过去 - 结束"值之外(可能由end()容器上的函数返回)或者在迭代器的有效范围的第一个可解除引用的元素之前前进(可能由begin()容器返回)是未定义的行为因为你违反了++或--操作的先决条件.
由于它是未定义的行为,你无法"期待"任何特别的东西.但是你可能会在某些时候崩溃(希望更早而不是更晚,所以你可以修复这个bug).
根据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)是未定义的.
您已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。
| 归档时间: |
|
| 查看次数: |
9103 次 |
| 最近记录: |