按顺序比较C ++迭代器是否安全

时间:2014-09-11 04:57:48

标签: c++ iterator

我试图将C ++的反向功能作为练习来实现。练习说明(来自Caltech的高级C ++课程)暗示您应该使用distance函数,该函数计算两个迭代器之间的项数。使用这个提示,我编写了下面的函数,它看似起作用:

template <typename BidirectionalIterator>
void my_reverse(BidirectionalIterator first, BidirectionalIterator last) {
    last--; // input "last" is one past the end
    while( first != last && distance(first, last) > 1 ){
        std::swap(*first, *last);
        first++;
        last--;
    }
    return;
}

但我对此方法有疑问:如果我没有弄错,在每一步调用distance会使其成为O(n ^ 2)算法。 所以我用以下内容替换了while条件:

    while( first < last ){

这似乎也有效。但它让我有点紧张,因为BidirectionalIterators上的文档并不能保证迭代器可以像这样订购。我是否可以相信此排序将始终按预期工作,v.end()对于STL容器对象v.begin()始终大于v

(我的担忧来自于像Haskell程序员一样认为BidirectionalIterators可以保证具有Eq的属性,可以这么说,但不是Ord。)

3 个答案:

答案 0 :(得分:3)

双向迭代器(也不是随机访问迭代器)不支持operator<。尝试将std::list迭代器传递给您的函数,您将看到它无法编译。他们不支持这种操作的原因正是因为它非常昂贵。

至于使用distance

  如果我没有弄错的话,在每一步调用距离都会成为一个问题   O(n ^ 2)算法。

你是正确的 1 。这不是实现反向算法的好方法。没有必要获得迭代器之间的距离。您只能使用operator!=和/或operator==来执行此操作,这两个都是O(1)。

<子> 1。除非你传递随机访问迭代器,在这种情况下,距离将使用operator-,算法将是O(n),如预期的那样。

答案 1 :(得分:3)

如果有人将空范围(first == last)传递给它,您的算法会有未定义的行为,因为您在检查该条件之前递减last。你需要

void my_reverse(BidirectionalIterator first, BidirectionalIterator last) {
    while((first != last) && (first != --last)){
        std::swap(*first, *last);
        first++;
    }
    return;
}

而不是引用迭代器并在结果上调用std::swap,您可以使用std::iter_swap为您完成所有操作。

void my_reverse(BidirectionalIterator first, BidirectionalIterator last) {
    while((first != last) && (first != --last)){
        std::iter_swap(first, last);
        first++;
    }
    return;
}

答案 2 :(得分:0)

...也许

void my_reverse(BidirectionalIterator first, BidirectionalIterator last)
{
    while (first != last && --last != first)
    {
        std::swap(*first, *last);
        ++first;
    }
}

这里的事情是每次交换都需要在递增first和递减last(按任意顺序)之后完成,但它们彼此相等的点可能只在一次这样的操作之后已执行,因此对于每个执行swap,应该有两个可能会从循环中断开的比较。