C ++(stl)与Java中的迭代器在概念上有区别吗?

时间:2020-03-05 18:51:23  来源:igfitidea点击:

在离开了一段时间并尝试清除旧瓜后,我将返回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吸收了现有内容并围绕其建立约定。

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

解决方案

回答

是的,在概念上有很大的不同。 C ++使用了不同的迭代器"类"。有些用于随机访问(不同于Java),有些用于前向访问(类似于Java)。而甚至其他人也被用来写数据(例如,与transform一起使用)。

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

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

与Java / C#的微不足道的迭代器相比,它们更加有趣和强大。希望这些约定将使用C ++ 0x的Concepts进行整理。

回答

迭代器仅等效于按顺序遍历数组内容的琐碎情况下的指针。迭代器可以从许多其他来源提供对象:从数据库,从文件,从网络,从其他某种计算等。

回答

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

就像我们说的那样,在Java中,迭代器比C ++中对底层容器的了解更多。 C ++迭代器是通用的,一对迭代器可以表示任意范围:这可以是容器的子范围,也可以是多个容器的范围(请参阅http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdf或者http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html)或者什至一系列数字(请参阅http://www.boost.org/doc/libs/1_36_0 /libs/iterator/doc/counting_iterator.html)

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

回答

也许有点理论化。从数学上讲,C ++中的集合可以描述为迭代器的半开间隔,即一个迭代器指向集合的开始,一个迭代器指向最后一个元素。

这种约定为人们带来了无限可能。算法在C ++中的工作方式,都可以应用于更大集合的子序列。为了使这种事情在Java中起作用,我们必须围绕返回一个不同迭代器的现有集合创建一个包装器。

Frank已经提到了迭代器的另一个重要方面。迭代器有不同的概念。 Java迭代器与C ++的输入迭代器相对应,即它们是只读的迭代器,一次只能递增一个步骤,并且不能向后进行。

另一方面,我们有C指针,它们完全对应于C ++的随机访问迭代器的概念。

总而言之,C ++提供了更丰富,更纯净的概念,与C指针或者Java迭代器相比,它可以应用于种类繁多的任务。

回答

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

在C ++中,我们最终不得不使用一对迭代器。在Java中,我们可以使用迭代器或者集合。迭代器被认为是算法和数据结构之间的粘合剂。为1.5+编写的代码很少需要提及迭代器,除非它正在实现特定的算法或者数据结构(大多数程序员不需要这样做)。随着Java的发展,动态多态子集之类的子集更容易处理。

回答

对我来说,根本的区别是Java迭代器指向项目之间,而C ++ STL迭代器指向项目。

回答

C ++迭代器是指针概念的概括。它们使它适用于更广泛的情况。这意味着它们可用于执行定义任意范围的操作。

Java迭代器是相对愚蠢的枚举器(尽管不如C#的枚举器差;至少Java具有ListIterator并可用于对集合进行变异)。

回答

如前所述,Java和Citerator描述了位置(状态)和范围(值)的混合,而C ++迭代器将位置和范围的概念分开。 C ++迭代器分别表示"我现在在哪里"和"我可以去哪里?"。

Java和Citerators无法复制。我们无法恢复以前的职位。常见的C ++迭代器可以。

考虑以下示例:

// 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)时间
  • 或者将特定的Array类型与GetAt成员函数一起使用,会失去泛型性和使用链接列表容器类型的能力。

由于在此示例中仅使用了正向迭代机制,因此我可以毫无问题地交换列表。这对于编写通用算法(例如搜索,延迟的初始化和评估,排序等)至关重要。

无法保留状态与C ++ STL输入迭代器最接近,后者基于很少的算法构建。