如果你增加一个迭代器等于一个STL容器的结束迭代器会发生什么如果你增加一个迭代器等于一个STL容器的

2019-05-14 02:01发布

如果我增加了2迭代器时,它指向到一个向量的最后一个元素? 在这个问题问如何通过2元两种不同的方法可供调整迭代STL容器:

  • 既可以使用算术运算器的一种形式 - + = 2或两次++
  • 或者使用std ::提前()

我已经与VC ++ 7的边缘的情况下进行测试两者当迭代点到STL容器或超出的最后一个元素:

vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );

vector<int>::iterator it = vec.begin();
advance( it, 2 );
bool isAtEnd = it == vec.end(); // true
it++; // or advance( it, 1 ); - doesn't matter
isAtEnd = it == vec.end(); //false
it = vec.begin();
advance( it, 3 );
isAtEnd = it == vec.end(); // false

遍历向量和其他容器时,我见过5次的提醒来比较矢量::结束():

for( vector<int>::iterator it = vec.begin(); it != vec.end(); it++ ) {
    //manipulate the element through the iterator here
}

显然,如果迭代器前进经过循环中的最后一个元素的for循环语句的比较将计算为假,循环会很乐意继续为未定义行为。

我得到它的权利,如果我曾经使用上一个迭代提前()或任何类型的增值业务,并使其指向过去容器的最后,我将无法检测到这种情况呢? 如果是这样,什么是最好的做法 - 不要用这样的进步?

Answer 1:

以下是从尼古拉约祖蒂斯书报价:

请注意,提前()不检查它是否跨越序列的末尾()(它不能检查,因为在一般的迭代器不知道其运行的容器)。 因此,调用此函数可能导致不确定的行为,因为调用operator ++的序列的末尾没有定义

换句话说,维护范围内的迭代器的责任在于完全与呼叫者。



Answer 2:

也许你应该有这样的事情:

template <typename Itr>
Itr safe_advance(Itr i, Itr end, size_t delta)
{
    while(i != end && delta--)
        i++;
    return i;
}

您可以在这个过载iterator_category<Itr>random_access_iterator做类似如下:

return (delta > end - i)? end : i + delta;


Answer 3:

你可以在vec.begin()使用你的迭代器(它)和迭代器之间的“距离”的功能,并将其与向量的大小比较(按大小得到())。

在这种情况下,你的循环应该是这样的:

for (vector<int>::iterator it = vec.begin(); distance(vec.begin(), it) < vec.size(); ++it)
{
     // Possibly advance n times here.
}


Answer 4:

该Marijn暗示的代码只是稍有不当(如curiousguy指出)。

最后一行的正确的版本是:

bool isPastEnd = it >= vec.end();


Answer 5:

我建议你看一看Boost.Range 。
这可能是使用更安全。
这也将是C ++ 0x中。



Answer 6:

container.end() - 元素刚刚过去的端 - 是唯一定义的外部值。

一检查迭代器故障在本质上是超出范围的访问,但这是不是非常有帮助的(特别是作为默认行为是结束程序)。

我认为最好的做法是“不这样做” - 无论是检查迭代器(最好的东西包装成一个过滤器)的每一个值,只有在有趣的条目进行操作,或者明确地使用索引

对(INT I = 0;我vec.size()<; I + = 2){...}



Answer 7:

你也可以做更多的比较在您的发言:

for( vector<int>::iterator it = vec.begin(); it != vec.end() && it+1 != vec.end(); it+=2 ) {
    //manipulate the element through the iterator here
}

我不知道这将如何执行VS 科斯塔斯的建议,但感觉这将是一个小的增量更好。 当然,因为你需要为每一个检查,但它是另一种选择将是一个大的增量相当难以维护。

如果可能的话,我肯定会避免它。 如果你真的需要通过2个值在一个时间递增,则考虑有性病的矢量::对或结构的2个元素的向量。



Answer 8:

尽管这个问题是半年,旧,但它仍然可能是有用的提及使用比较运算符>和<检查,如果你重复过去的结束(或迭代回来的时候开始)的容器。 例如:

vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );

vector<int>::iterator it = vec.begin();

it+=10; //equivalent to advance( it, 10 )
bool isPastEnd = it > vec.end(); //true


文章来源: What happens if you increment an iterator that is equal to the end iterator of an STL container