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

sha*_*oth 62 c++ iterator stl vector

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

  • 使用算术运算符的形式 - + = 2或++两次
  • 或者使用std :: advance()

当迭代器指向STL容器的最后一个元素或更远时,我用VC++ 7测试了它们的边缘情况:

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
Run Code Online (Sandbox Code Playgroud)

我已经看过有时可以建议在遍历vector和其他容器时与vector :: end()进行比较:

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

显然,如果迭代器超出循环内的最后一个元素,则for循环语句中的比较将评估为false,并且循环将很快继续进入未定义的行为.

我是否正确,如果我在迭代器上使用advance()或任何类型的递增操作并使它指向容器的末尾,我将无法检测到这种情况?如果是这样,最佳做法是什么 - 不使用这些进步?

Nav*_*een 62

以下是Nicolai Josuttis的书:

请注意,advance()不会检查它是否越过序列的end()(它无法检查,因为迭代器通常不知道它们运行的​​容器).因此,调用此函数可能会导致未定义的行为,因为未定义为序列末尾调用operator ++

换句话说,将迭代器维持在范围内的责任完全在于调用者.

  • 算术运算后如何检查它是否在范围内? (2认同)
  • @Narek你不能。在 C++ 中,在可能出现 UB 的操作之后进行检查始终是一个失败的策略。 (2认同)

Mot*_*tti 14

也许你应该有这样的东西:

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

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

return (delta > end - i)? end : i + delta;
Run Code Online (Sandbox Code Playgroud)


Kos*_*tas 7

您可以在迭代器(it)和vec.begin()上的迭代器之间使用"distance"函数,并将其与向量的大小(通过size()获得)进行比较.

在这种情况下,你的for循环看起来像这样:

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

  • 它更多地与为每种类型的迭代器实现operator ++的方式有关."距离"计算向一个迭代器执行多少++或 - 必须执行多少++才能到达另一个迭代器.如果我是你,我会尝试在我期望的所有类型的容器上,看看距离给我的距离. (2认同)
  • 距离针对随机访问迭代器进行了优化:它的复杂度为O(1),因为它不计算++,但执行减法 (2认同)
  • @jalf"_distance()适用于任何输入iterator_":你可能不想这样做! (2认同)