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

时间:2011-07-13 03:31:07

标签: c++ stl iterator comparison-operators

我习惯写这样的循环:

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

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

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

我发现iterator != foo.end()要输掉了。如果iterator增加一个以上也是危险的。

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

2 个答案:

答案 0 :(得分:72)

所有迭代器都具有可比性。只有随机访问迭代器才具有可比性。输入迭代器,前向迭代器和双向迭代器在关系上没有可比性。

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


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

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

  • 如果您将迭代器放入链表并且想要测试一个迭代器是否“小于”另一个迭代器,则必须从一个迭代器中走链接列表的节点,直到您到达另一个迭代器迭代器或你到达列表的末尾。

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


此外,不允许将迭代器增加到它指向的范围的末尾。因此,如果您最终遇到it != foo.end()it < foo.end()不同的情况,那么您已经有了未定义的行为,因为您已经遍历了范围的末尾。

对于指向数组的指针也是如此:不允许将指针递增超出数组的一端;这样做的程序展示了未定义的行为。 (对于指数来说,情况显然不同,因为指数只是整数。)

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

答案 1 :(得分:11)

简短回答:因为Iterator不是数字,所以它是一个对象。

更长的答案:收集的数量多于线性数组。例如,树和哈希并不真正适用于“此索引在此其他索引之前”。例如,对于树,两个索引位于不同的分支上。或者,哈希中的任何两个索引 - 它们根本没有订单,因此您对它们施加的任何订单都是任意的。

您不必担心“遗失”End()。它也不是数字,它是表示集合结束的对象。有一个经过它的迭代器是没有意义的,事实上它不能。