为什么“!=”与迭代器一起使用?(Why is “!=” used with iterators instead of “

编程入门 行业动态 更新时间:2024-10-24 08:31:02
为什么“!=”与迭代器一起使用?(Why is “!=” used with iterators instead of “<”?)

我习惯写这样的循环:

for (std::size_t Index = 0; Index < Foo.Size(); Index++) { // Do stuff with Foo[Index]. }

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

for (Bar::Iterator Iterator = Foo.Begin(); Iterator != Foo.End(); Foo++) { // Do stuff with *Iterator. }

我发现Iterator != Foo.End()被放弃。 如果Iterator递增多于一个也可能是危险的。

使用Iterator < Foo.End()似乎更“正确”,但我从来没有看到真正的代码。 为什么不?

I'm used to writing loops like this:

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. }

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

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

最满意答案

所有的迭代器都是相等的。 只有随机访问迭代器是可比较的。 输入迭代器,前向迭代器和双向迭代器不是关系可比的。

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


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

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

如果您将迭代器插入到链表中,并且您想要测试一个迭代器是否“小于”另一个迭代器,则必须从一个迭代器中遍历链表的节点,直到到达其他迭代器或到达结束的列表。

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


此外,您不能将迭代器增加到其指向的范围的末尾。 所以,如果你最终在一个场景中it != foo.end()不像it < foo.end() ,你已经有了未定义的行为,因为你已经遍历了范围的末尾。

对于指向数组的指针也是如此:您不能将指针递增超出数组的一端; 这样做的程序表现出未定义的行为。 (索引显然不是这样,因为索引只是整数。)

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

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.


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.)

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.

更多推荐

本文发布于:2023-07-08 20:08:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1080290.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:迭代   iterators

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!