C++ 中的迭代器 (stl) 与 Java,有概念上的区别吗?
在离开一段时间并试图掸掉旧瓜上的灰尘后,我又回到了 C++。
在 Java 中,迭代器是容器的接口,具有以下方法: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 采用现有的内容并围绕它构建约定。
我是否还缺少任何进一步的微妙之处?
I'm returning to c++ after being away for a bit and trying to dust off the old melon.
In Java Iterator is an interface to a container having methods: hasNext()
, next()
and remove()
. The presence of hasNext()
means it has the concept of a limit for the container being traversed.
//with an Iterator
Iterator<String> iter = trees.iterator();
while (iter.hasNext())
{
System.out.println(iter.next());
}
In the C++ standard template library, iterators seem to represent a datatype or class the supports the operator++
and operator==
but has no concept of a limit built in so comparison is required before advancing to the next item. The limit has to checked by the user comparing two iterators in the normal case the second iterator is the container end.
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
}
The interesting part here is that in C++ a pointer is an iterator to an array. The STL took what was existing and build convention around it.
It there any further subtlety to this that I am missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
指向数组元素的指针实际上是数组的迭代器。
正如您所说,在 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)
迭代器类别标识了给定迭代器可以做什么和不能做什么。
A pointer to an array element is indeed an iterator into the array.
As you say, in Java, an iterator has more knowledge of the underlying container than in C++. C++ iterators are general, and a pair of iterators can denote any range: this can be a sub-range of a container, a range over multiple containers (see http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdf or http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html) or even a range of numbers (see http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/counting_iterator.html)
The iterator categories identify what you can and can't do with a given iterator.
C++ 库(以前称为 STL 的部分)迭代器被设计为与指针兼容。 Java 没有指针运算,因此可以自由地对程序员更加友好。
在 C++ 中,您最终必须使用一对迭代器。 在 Java 中,您可以使用迭代器或集合。 迭代器应该是算法和数据结构之间的粘合剂。 为 1.5+ 编写的代码很少需要提及迭代器,除非它正在实现特定的算法或数据结构(大多数程序员不需要这样做)。 由于 Java 追求动态多态性,子集等更容易处理。
C++ library (the part formerly known as STL) iterators are designed to be compatible with pointers. Java, without pointer arithmetic, had the freedom to be more programmer-friendly.
In C++ you end up having to use a pair of iterators. In Java you either use an iterator or a collection. Iterators are supposed to be the glue between algorithm and data structure. Code written for 1.5+ rarely need mention iterators, unless it is implementing a particular algorithm or data structure (which the vary majority of programmers have no need to do). As Java goes for dynamic polymorphism subsets and the like are much easier to handle.
对我来说,根本区别在于 Java 迭代器指向项之间,而 C++ STL 迭代器指向项。
To me the fundamental difference is that Java Iterators point between items, whereas C++ STL iterators point at items.
C++ 迭代器是指针概念的推广; 它们使其适用于更广泛的情况。 这意味着它们可以用来做定义任意范围之类的事情。
Java 迭代器是相对愚蠢的枚举器(尽管没有 C# 的那么糟糕;至少 Java 有 ListIterator 并且可以用来改变集合)。
C++ iterators are a generalization of the pointer concept; they make it applicable to a wider range of situations. It means that they can be used to do such things as define arbitrary ranges.
Java iterators are relatively dumb enumerators (though not so bad as C#'s; at least Java has ListIterator and can be used to mutate the collection).
关于这些差异,有很多很好的答案,但我觉得 Java 迭代器最让我烦恼的事情没有被强调——你不能多次读取当前值。 这在很多场景中都非常有用,特别是当您合并迭代器时。
在 C++ 中,您有一种方法可以推进迭代器并读取当前值。 读取它的值不会推进迭代; 所以你可以多次阅读。 这对于 Java 迭代器来说是不可能的,我最终创建了执行此操作的包装器。
附注:创建包装器的一种简单方法是使用现有的包装器 -PeekingIterator。
There are plenty of good answers about the differences, but I felt the thing that annoys me the most with Java iterators wasn't emphasized--You can't read the current value multiple times. This is really useful in a lot of scenarios, especially when you are merging iterators.
In c++, you have a method to advance the iterator and to read the current value. Reading its value doesn't advance the iteration; so you can read it multiple times. This is not possible with Java iterators, and I end up creating wrappers that do this.
A side note: one easy way to create a wrapper is to use an existing one--PeekingIterator from Guava.
仅在按顺序迭代数组内容的简单情况下,迭代器才相当于指针。 迭代器可以从任意数量的其他源提供对象:从数据库、从文件、从网络、从其他计算等。
Iterators are only equivalent to pointers in the trivial case of iterating over the contents of an array in sequence. An iterator could be supplying objects from any number of other sources: from a database, from a file, from the network, from some other calculation, etc.
是的,概念上存在很大差异。 C++ 使用不同“类”的迭代器。 有些用于随机访问(与Java不同),有些用于前向访问(如java)。 甚至还有一些用于写入数据(例如,与
transform
一起使用)。请参阅 C++ 文档中的迭代器概念:
与 Java/C# 的小迭代器相比,这些迭代器更加有趣和强大。 希望这些约定将使用 C++0x 的概念进行编码。
Yes, there is a large conceptual difference. C++ utilizes different "classes" of iterators. Some are used for random access (unlike Java), some are used for forward access (like java). While even others are used for writing data (for use with, say,
transform
).See the iterators concept in the C++ Documentation:
These are far more interesting and powerful compared to Java/C#'s puny iterators. Hopefully these conventions will be codified using C++0x's Concepts.
如前所述,Java 和 C# 迭代器描述了混合的位置(状态)和范围(值),而 C++ 迭代器则分离了位置和范围的概念。 C++ 迭代器分别代表“我现在在哪里”和“我能去哪里?”。
Java 和 C# 迭代器无法复制。 您无法恢复之前的位置。 常见的 C++ 迭代器可以。
考虑此示例:
单击上面的链接查看程序输出。
这个相当愚蠢的循环遍历一个序列(仅使用前向迭代器语义),将 3 个元素的每个连续子序列打印一次(并在末尾打印几个较短的子序列)。 但假设 N 个元素,每行 M 个元素而不是 3 个,该算法仍然是 O(N*M) 迭代器增量和 O(1) 空间。
Java 风格的迭代器缺乏独立存储位置的能力。 您将
由于本示例中仅使用前向迭代机制,因此我能够在列表中进行交换,没有问题。 这对于编写通用算法至关重要,例如搜索、延迟初始化和评估、排序等。
无法保留状态与 C++ STL 输入迭代器最接近,很少有算法是基于该迭代器构建的。
As mentioned, Java and C# iterators describe an intermixed position(state)-and-range(value), while C++ iterators separate the concepts of position and range. C++ iterators represent 'where am I now' separately from 'where can I go?'.
Java and C# iterators can't be copied. You can't recover a previous position. The common C++ iterators can.
Consider this example:
Click the above link to see program output.
This rather silly loop goes through a sequence (using forward iterator semantics only), printing each contiguous subsequence of 3 elements exactly once (and a couple shorter subsequences at the end). But supposing N elements, and M elements per line instead of 3, this algorithm would still be O(N*M) iterator increments, and O(1) space.
The Java style iterators lack the ability to store position independently. You will either
Since only forward iteration mechanics were used in this example, i was able to swap in a list with no problems. This is critical to authoring generic algorithms, such as search, delayed initialization and evaluation, sorting, etc.
The inability to retain state corresponds most closely to the C++ STL input iterator, on which very few algorithms are built.
也许更理论一点。 从数学上讲,C++ 中的集合可以描述为迭代器的半开区间,即一个迭代器指向集合的开头,另一个迭代器指向最后一个元素的后面。
这次会议开启了许多可能性。 算法在 C++ 中的工作方式一样,它们都可以应用于更大集合的子序列。 为了让这样的事情在 Java 中工作,您必须围绕现有集合创建一个包装器,该包装器返回不同的迭代器。
Frank 已经提到了迭代器的另一个重要方面。 迭代器有不同的概念。 Java迭代器对应于C++的输入迭代器,即它们是只读迭代器,一次只能递增一步并且不能向后移动。
在另一个极端,您拥有与 C++ 的随机访问迭代器概念完全对应的 C 指针。
总而言之,C++ 提供了比 C 指针或 Java 迭代器更丰富、更纯粹的概念,可以应用于更广泛的任务。
Perhaps a bit more theoretical. Mathematically, collections in C++ can be described as a half-open interval of iterators, namely one iterator pointing to the start of the collection and one iterator pointing just behind the last element.
This convention opens up a host of possibilities. The way algorithms work in C++, they can all be applied to subsequences of a larger collection. To make such a thing work in Java, you have to create a wrapper around an existing collection that returns a different iterator.
Another important aspect of iterators has already been mentioned by Frank. There are different concepts of iterators. Java iterators correspond to C++' input iterators, i.e. they are read-only iterators that can only be incremented one step at a time and can't go backwards.
On the other extreme, you have C pointers which correspond exactly to C++' concept of a random access iterator.
All in all, C++ offers a much richer and purer concept that can be applied to a much wider variety of tasks than either C pointers or Java iterators.