为什么是“!="?与迭代器一起使用而不是“<"?

2022-01-07 00:00:00 iterator comparison-operators c++ stl

我习惯写这样的循环:

for (std::size_t index = 0; index < foo.size(); index++)
{
    // Do stuff with foo[index].
}

但是当我在其他人的代码中看到迭代器循环时,它们看起来像这样:

But when I see iterator loops in others' code, they look like this:

for (Foo::Iterator iterator = foo.begin(); iterator != foo.end(); iterator++)
{
    // Do stuff with *Iterator.
}

我发现 iterator != foo.end() 令人反感.如果 iterator 的增量超过 1,也可能很危险.

I find the iterator != foo.end() to be offputting. It can also be dangerous if iterator is incremented by more than one.

使用 iterator < 似乎更正确"foo.end(),但我从未在实际代码中看到过.为什么不呢?

It seems more "correct" to use iterator < foo.end(), but I never see that in real code. Why not?

推荐答案

所有迭代器都是相等可比的.只有随机访问迭代器是关系可比的.输入迭代器、前向迭代器和双向迭代器没有关系可比性.

All iterators are equality comparable. Only random access iterators are relationally comparable. Input iterators, forward iterators, and bidirectional iterators are not relationally comparable.

因此,使用 != 的比较比使用 < 的比较更通用和灵活.

Thus, the comparison using != is more generic and flexible than the comparison using <.

迭代器有不同的类别,因为并非所有元素范围都具有相同的访问属性.例如,

There are different categories of iterators because not all ranges of elements have the same access properties. For example,

  • 如果你有一个迭代器进入一个数组(一个连续的元素序列),对它们进行关系比较是微不足道的;您只需要比较指向元素的索引(或指向它们的指针,因为迭代器可能只包含指向元素的指针);

  • if you have an iterators into an array (a contiguous sequence of elements), it's trivial to relationally compare them; you just have to compare the indices of the pointed to elements (or the pointers to them, since the iterators likely just contain pointers to the elements);

如果你有一个链表的迭代器,并且你想测试一个迭代器是否小于"另一个迭代器,你必须从一个迭代器遍历链表的节点,直到你到达另一个迭代器或到达列表末尾.

if you have iterators into a linked list and you want to test whether one iterator is "less than" another iterator, you have to walk the nodes of the linked list from the one iterator until either you reach the other iterator or you reach the end of the list.

规则是迭代器上的所有操作都应该具有恒定的时间复杂度(或者,至少是次线性的时间复杂度).您始终可以在恒定时间内执行相等比较,因为您只需要比较迭代器是否指向同一个对象.因此,所有迭代器都是相等可比的.

The rule is that all operations on an iterator should have constant time complexity (or, at a minimum, sublinear time complexity). You can always perform an equality comparison in constant time since you just have to compare whether the iterators point to the same object. So, all iterators are equality comparable.

此外,您不能将迭代器递增到它所指向的范围的末尾.因此,如果您最终遇到 it != foo.end()it < 不一样的情况.foo.end(),您已经有未定义的行为,因为您已经迭代超过范围的末尾.

Further, you aren't allowed to increment an iterator past the end of the range into which it points. So, if you end up in a scenario where it != foo.end() does not do the same thing as it < foo.end(), you already have undefined behavior because you've iterated past the end of the range.

对于指向数组的指针也是如此:不允许将指针增加到数组的末尾;这样做的程序表现出未定义的行为.(对于索引显然不是这样,因为索引只是整数.)

The same is true for pointers into an array: you aren't allowed to increment a pointer beyond one-past-the-end of the array; a program that does so exhibits undefined behavior. (The same is obviously not true for indices, since indices are just integers.)

某些标准库实现(如 Visual C++ 标准库实现)具有有用的调试代码,当您使用这样的迭代器执行非法操作时,这些代码将引发断言.

Some Standard Library implementations (like the Visual C++ Standard Library implementation) have helpful debug code that will raise an assertion when you do something illegal with an iterator like this.

相关文章