【发布时间】:2010-06-14 06:49:17
【问题描述】:
我找到了类似的话题:
Iterators in C++ (stl) vs Java, is there a conceptual difference?
这主要是处理 Java 迭代器(类似于 C#)无法后退的问题。
所以在这里我想关注限制——在 C++ 中,迭代器不知道它的限制,你必须自己将给定的迭代器与限制进行比较。在 C# 中,迭代器了解更多——您无需与任何外部引用进行比较即可判断迭代器是否有效。
我更喜欢 C++ 方式,因为一旦有了迭代器,您就可以将任何迭代器设置为限制。换句话说,如果您只想获取几个元素而不是整个集合,则不必更改迭代器(在 C++ 中)。对我来说它更“纯粹”(清晰)。
当然,MS 在设计 C# 时就知道这一点和 C++。那么C#方式有哪些优势呢?哪种方法更强大(这会导致基于迭代器的更优雅的函数)。我错过了什么?
如果您对 C# 与 C++ 迭代器设计的限制(边界)以外的其他想法,也请回答。
注意:(以防万一)请保持讨论严格的技术性。没有 C++/C# 火焰战争。
编辑
正如 Tzaman 所说,“将限制单独表示没有任何好处,因为除了一次走一个元素外,没有其他方法可以到达那里。”然而,构建一个一次执行几个步骤的 C# 迭代器并不难,因此问题是——具有显式限制迭代器(如在 C++ 中)是否有好处?如果是 - 什么?
@乔恩,
Edit1: 假设你有一个函数 foo,它在迭代器上做一些事情(这个例子很天真!)
void foo(iter_from,iter_end) // C++ style
void foo(iter) // C# style
现在你想在除最后 10 个元素之外的所有元素上调用功能栏。
bar(iter_from,iter_end-10); // C++ style
在 C# 中(如果我没记错的话)你必须为这个迭代器提供额外的方法来改变 its 限制,像这样:
bar(iter.ChangeTheLimit(-10));
Edit2: 重读您的帖子后,我感受到了至关重要的不同。在 C++ 中,您处理集合的迭代器,在 C# 中,您处理集合(迭代器在“内部”使用)。如果是的话,我仍然对 C# 感到有点不舒服——你迭代集合,当你发现有趣的元素时,你想将所有元素从“这里”传递到结束。在 C++ 中,这非常容易,并且没有开销。在 C# 中,您可以传递一个迭代器或一个集合(如果后者将有额外的计算)。我会等你的评论:-)
@汉斯,
我不是在比较苹果和橘子。比较。理论在这里是共同点,所以你有排序算法、分区等。你有集合的概念(或序列,正如 Jon 喜欢的那样)。现在 - 问题是您如何设计对元素的访问以拥有用 C# 或 C++(或任何其他语言)编写的优雅算法。我想理解“我们这样做是因为……”的原因。
我知道 .NET 迭代器和集合是独立的类。我知道访问元素和整个集合之间的区别。然而,在 C++ 中,处理集合的最通用方法是使用迭代器——尽管这些集合完全不同,但您可以通过这种方式使用列表和向量。另一方面,在 C# 中,您更愿意编写
sort(IEnumerable<T> coll)
改为函数
sort(IEnumerator<T> iter)
正确吗?所以从这个意义上说,我猜你不能把 C# 迭代器当作 C++ 迭代器,因为 C# 并不像 C++ 那样表达相同的算法。或者正如 Jon 指出的那样——在 C# 中,您宁愿转换集合(Skip、Take)而不是更改迭代器。
【问题讨论】:
-
@macias,因为既不是 C++ 也不是 C# 开发人员,我更喜欢您示例中的 C# 风格。对我来说它看起来更自然。
-
C++ 中如何处理无限序列?在这种情况下 iter_end 会是什么?
-
@Damien,我从未在 C++ 中使用过不定式序列。
-
两个字:责任原则。
-
@Damien:对于无限序列,
iter_end必须是一个永远不会达到的特殊值(例如,如果流永远不会结束,istream_iterator 可以表示无限范围)。但是,如果一种算法被设计为使用无限序列,它可能只需要一个迭代器。例如,算法std::copy采用两个输入迭代器来表示源范围(或序列),但只有一个输出迭代器,它或多或少可以看作是一个无限的复制范围。 [...]