【发布时间】:2010-10-27 08:09:28
【问题描述】:
Iterator 在 Java 中的实现与在 C++ 中的实现有何不同?
【问题讨论】:
-
您的问题必须更加明确。你到底有什么问题?
-
@litb 刚刚读完!!
Iterator 在 Java 中的实现与在 C++ 中的实现有何不同?
【问题讨论】:
在当前的 C++ (98) 标准库(特别是以前称为 STL 的部分)中定义了一种非常接近 C 指针(包括算术)的迭代器。因此,他们只是指向某个地方。为了有用,您通常需要两个指针,以便您可以在它们之间进行迭代。我知道 C++0x 引入了更像 Java 迭代器的范围。
Java 在 1.2 中引入了Iterator(和ListIterator)接口,很大程度上取代了更冗长的 Enumerable。 Java 没有指针算法,所以没有必要表现得像一个指针。他们有一个hasNext 方法来查看他们是否已经走到最后,而不是需要两个迭代器。缺点是它们不太灵活。系统要求方法为subList,而不是在两个迭代器之间迭代是包含列表中的特定点。
风格上的一个普遍区别是,C++ 通过模板使用“静态多态”,而 Java 使用接口和常见的动态多态。
迭代器的概念是提供粘合剂以允许分离“算法”(真正的控制流)和数据容器。这两种方法都做得相当好。在理想情况下,“正常”代码应该几乎看不到迭代器。
【讨论】:
实现完全由标准库供应商/JRE 供应商分别在 C++/Java 中定义。只要他们的行为符合各自的标准,他们就可以随意实现它们。
【讨论】:
在 C++ 中,您会看到人们一直在传递迭代器。 C++ 迭代器“指向”容器的特定元素。您可以取消引用迭代器来获取元素(您可以一遍又一遍地这样做)。您可以有效地擦除迭代器引用的元素。您还可以复制迭代器(通过分配给另一个变量,或将迭代器按值传递给函数)以同时跟踪多个位置。 C++ 中的迭代器可能会因容器上的某些操作而“无效”,具体取决于容器。当迭代器失效(其规则可能很复杂)时,使用迭代器的操作具有未定义的行为,并且可能(不一致地)使您的程序崩溃或返回不正确的结果;尽管在某些数据结构中(例如std::list),迭代器在容器的大多数修改中仍然有效。
在 Java 中,您看不到这种用法。 Java 中的迭代器指向两个元素“之间”,而不是“在”一个元素。使用迭代器获取元素的唯一方法是将其向前移动以获取移动过的元素。当然,这会改变迭代器的状态,并且您无法返回;除非你有ListIterator,在这种情况下你可以向前和向后移动(但为了保持静止而必须向前和向后移动仍然很烦人)。您不能复制迭代器,因为接口没有公开公共复制方法;因此,例如,您不能只将特定位置的标记传递给函数,而不向该函数提供对您拥有的相同迭代器的引用,从而允许它们更改迭代器的状态。在 Java 中,除了通过迭代器自己的 add() 或 remove() 方法之外,对容器的任何修改都会使迭代器失效(至少在标准容器中),这过于保守(例如,对 LinkedList 的大多数修改应该不影响迭代器)。当您尝试使用无效的迭代器时,它会引发 ConcurrentModificationException(之所以命名混淆,是因为它与并发无关)而不是可能导致未定义的行为,这很好。
【讨论】:
C++ 没有指定迭代器是如何实现的。然而,它确实指定了它们的接口和它们必须提供的最小行为,以便与其他标准库组件一起工作。
例如,对于输入迭代器,标准规定迭代器必须可以通过 * 运算符取消引用。但是,它没有指定如何实现该运算符。
【讨论】:
C++ 迭代器 (STL) 尝试通过运算符重载尽可能多地模仿指针语法。
标准规范定义了各种迭代器概念(如前向、双向、随机访问、输入、输出)。每个概念都应该匹配一个特定的接口(例如,用于前向迭代器的 ++ 运算符以按顺序转到下一个元素,-- 用于双向,+、+= 用于随机访问等)。
【讨论】: