C ++(stl)与Java中的迭代器是否存在概念上的差异?

时间:2008-09-11 11:50:24

标签: java c++ iterator iteration

我离开后稍微回到c ++,试图把老瓜弄脏。

在Java中,Iterator是具有方法的容器的接口:hasNext(),next()和remove()。 hasNext()的存在意味着对于被遍历的容器具有限制的概念。

//with an Iterator
Iterator<String> iter = trees.iterator();
while (iter.hasNext()) 
{
    System.out.println(iter.next());
}

在C ++标准模板库中,迭代器似乎表示支持operator ++和operator ==的数据类型或类,但内置了没有限制的概念,因此在进入之前需要进行比较。下一个项目。用户必须检查限制,比较正常情况下的两个迭代器,第二个迭代器是容器端。

vector<int> vec;
vector<int>::iterator iter;

// Add some elements to vector
v.push_back(1);
v.push_back(4);
v.push_back(8);

for(iter= v.begin(); iter != v.end(); iter++)
{
    cout << *i << " "; //Should output 1 4 8
}

这里有趣的部分是在C ++中,指针是数组的迭代器。 STL采用了现有的并围绕它构建惯例。

我还缺少任何进一步的微妙之处吗?

8 个答案:

答案 0 :(得分:20)

也许更理论化。在数学上,C ++中的集合可以描述为迭代器的半开放区间,即一个指向集合开头的迭代器和一个指向后面最后一个元素的迭代器。

这一惯例开辟了许多可能性。算法在C ++中的工作方式,它们都可以应用于更大集合的子序列。要使这样的东西在Java中工作,你必须围绕一个返回不同迭代器的现有集合创建一个包装器。

Frank已经提到了迭代器的另一个重要方面。迭代器有不同的概念。 Java迭代器对应于C ++的输入迭代器,即它们是只读迭代器,一次只能递增一步,不能倒退。

另一方面,你有C指针,它们完全符合C ++的随机访问迭代器概念。

总而言之,C ++提供了更丰富,更纯粹的概念,可以应用于比C指针或Java迭代器更广泛的任务。

答案 1 :(得分:18)

是的,存在很大的概念差异。 C ++使用不同的“类”迭代器。一些用于随机访问(与Java不同),一些用于前向访问(如java)。甚至其他人也用于编写数据(例如,用于transform)。

请参阅C++ Documentation中的迭代器概念:

  • 输入迭代器
  • 输出迭代器
  • Forward Iterator
  • 双向迭代器
  • 随机访问迭代器

与Java / C#的微弱迭代器相比,它们更有趣,更强大。希望这些约定将使用C ++ 0x Concepts进行编码。

答案 2 :(得分:11)

如前所述,Java和C#迭代器描述了混合位置(状态)和范围(值),而C ++迭代器分隔了位置和范围的概念。 C ++迭代器代表'我现在在哪里'与“我可以去哪里?”分开。

无法复制Java和C#迭代器。你无法恢复以前的位置。常见的C ++迭代器可以。

考虑this example

// for each element in vec
for(iter a = vec.begin(); a != vec.end(); ++a){
  // critical step!  We will revisit 'a' later.
  iter cur = a; 
  unsigned i = 0;
  // print 3 elements
  for(; cur != vec.end() && i < 3; ++cur, ++i){
      cout << *cur << " ";
  }
  cout << "\n";
}

点击以上链接查看节目输出。

这个相当愚蠢的循环遍历一个序列(仅使用前向迭代器语义),只打印3个元素的每个连续子序列一次(以及最后几个较短的子序列)。但是假设N个元素和每行M个元素而不是3个,这个算法仍然是O(N * M)迭代器增量和O(1)空间。

Java样式迭代器缺乏独立存储位置的能力。你会

  • 丢失O(1)空间,使用(例如)大小为M的数组来存储历史记录
  • 将需要遍历列表N次,使得O(N ^ 2 + N * M)时间
  • 或使用具有GetAt成员函数的具体Array类型,失去通用性和使用链表容器类型的能力。

由于在此示例中仅使用了前向迭代机制,因此我能够使用no problems交换列表。这对于编写通用算法至关重要,例如搜索,延迟初始化和评估,排序等。

无法保留状态最接近于C ++ STL输入迭代器,在该迭代器上构建的算法非常少。

答案 3 :(得分:7)

指向数组元素的指针确实是数组的迭代器。

正如你所说,在Java中,迭代器比C ++更了解底层容器。 C ++迭代器是通用的,迭代器的可以表示任何范围:这可以是容器的子范围,多个容器的范围(请参阅http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdf或{{3} })甚至一系列数字(见http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html

迭代器类别标识了给定迭代器可以做什么和不能做什么。

答案 4 :(得分:3)

对我而言,根本区别在于Java Iterators指向项目之间,而C ++ STL迭代器指向项目。

答案 5 :(得分:2)

C ++迭代器是指针概念的概括;它们使其适用于更广泛的情况。这意味着它们可以用来做定义任意范围的事情。

Java迭代器是相对愚蠢的枚举器(虽然没有C#那么糟糕;至少Java有ListIterator,可以用来改变集合)。

答案 6 :(得分:1)

迭代器只是在按顺序遍历数组内容的简单情况下等效于指针。迭代器可以从任意数量的其他来源提供对象:来自数据库,来自文件,来自网络,来自其他一些计算等。

答案 7 :(得分:1)

C ++库(以前称为STL的部分)迭代器旨在与指针兼容。没有指针算术的Java可以自由地使程序员更友好。

在C ++中,你最终不得不使用一对迭代器。在Java中,您可以使用迭代器或集合。迭代器应该是算法和数据结构之间的粘合剂。为1.5+编写的代码很少需要提及迭代器,除非它实现特定的算法或数据结构(大多数程序员不需要这样做)。由于Java适用于动态多态,因此子集等更易于处理。