C ++迭代器被认为有害吗?

时间:2009-05-08 08:05:32

标签: c++ iterator language-design

在今天的Boost图书馆会议上,{C ++ Design和Loki C ++库的作者Andrei Alexandrescu发表了题为“Iterators Must Go”的演讲(videoslides )关于为什么迭代器是坏的,他有一个更好的解决方案。

我试着阅读演示幻灯片,但我无法从中得到很多。

  1. 迭代器坏了吗?
  2. 他的替代品真的更好吗?
  3. C ++实现者会接受他的想法吗?

13 个答案:

答案 0 :(得分:40)

首先,回答你的问题:

  1. 否。事实上,我认为elsewhere迭代器是计算机科学中最重要/最基本的概念。我(与Andrei不同)也认为迭代器是直观的
  2. 是的,当然,但这不应该让人感到意外。
  3. 嗯。看Boost.Range和C ++ 0x - 他们已经没有了?
  4. Andrei在这里的重大贡献就是说:完全放弃迭代器的概念,不仅将范围看作是一个便利包装,而是作为一个核心结构。其他语言已经做到了这一点(Andrei的大部分概念只是回应.NET的LINQ或Python的迭代器),但它们都只提供输出范围。 Andrei认为不同类型的范围很像传统的迭代器类别。

    从这个角度来看,奇怪的是他开始嘲笑这些迭代器类别的任意性。

    我也认为他的例子已经关闭,特别是他的文件复制:是的,迭代器变体是对1975年代码的巨大改进。它将具有复杂中断条件的循环减少到一个语句。他在这里真正遇到的问题只是语法。好吧,对不起:我们在这里谈论C ++ - 当然语法很难看。是的,在这里使用范围 是一种改进 - 但只是语法上的。

    我也认为安德烈的find实施已经完成。他真正定义的是LINQ的DropUntil操作(命名很难!)。 find操作应该真正返回一个或零个元素(或迭代器!)。这里回避迭代器在我看来没有帮助,因为我们可能想直接修改值而不是复制它。在这里返回单元素范围只会增加开销而没有任何好处。这样做安德烈的方式很糟糕,因为这个方法的名称是错误的和误导性的。

    那就是说,我几乎在所有方面都基本同意安德烈。迭代器虽然是来自计算机科学的宠物概念,但肯定是一个很大的语法负担,许多范围(特别是无限生成器)可以(并且应该)在没有它们的情况下方便地实现。

答案 1 :(得分:4)

  1. 我们大多数人在已经成为众所周知的习语中简单地使用它们,比如for循环遍历std :: vector。开发人员读取它并知道发生了什么。在我们的日常编码生活中,迭代器并不好或坏,它们只是“完成任务的工作”。
  2. 可能,是的。
  3. 我不这么认为。

答案 2 :(得分:4)

安德烈有时候会有点挑衅。迭代器是一个合理的概念,在比特的意义上是非常基本的。但就像C ++中的大多数位不是bool,而是大型类型的一部分,大多数迭代器应该在高级别处理。安德烈是正确的,这样做的适当级别是范围对象。但是并非所有范围都作为迭代器范围正确公开,正如istream_iterator哨兵所示。这只是一个创建人工结束迭代器的黑客。不过,我认为他的想法不会被实施所吸引。 C ++ 1x与C99相关。

答案 3 :(得分:3)

我同意他的看法,迭代器大多不如射程,而且我不知道“更好的东西”是否会被拾取。

“好的是最好的敌人”在这里发挥着强烈的作用,就像通常那样。迭代器很有用且根深蒂固,因此很难知道范围更好的东西是否可以在合理的时间内取代它们。

答案 4 :(得分:3)

C ++ 0x已经迈出了第一步:

  • 右值引用解决了将容器视为范围的一些问题
  • 范围已添加到核心库,包括范围概念

转换到范围而不会丢失任何迭代器功能(想想迭代器类别,const-ness和rvalue-ness的所有组合)很难,特别是如果你试图考虑无限和可变范围。

答案 5 :(得分:3)

  1. 不,他们并不坏,事实上他们是非常聪明的主意。但是,它们并不理想,迭代器的概念还有改进的余地。

  2. 它解决了迭代器的一些现实问题。例如,在许多情况下,从单个容器中查询两个单独的对象迭代器然后将它们作为两个单独的对象传递给算法,这是繁琐的(也容易出错)。为什么不传递一个对象呢?即使std::pair<iterator, iterator>也会产生一个更容易操作的粗略范围 - 一个对象,而不是两个。此外,考虑a range is an iterator是个好主意。这实际上是安德烈建议的。顺便说一下,Boost.Range已经解决了其中一些问题。

  3. 我希望它会发生,但它不会是革命,而是进化。

答案 6 :(得分:2)

我认为我们应该在迭代器旁边使用范围,即我们应该选择进化方式,而不是革命方式。

答案 7 :(得分:2)

Andrei是不是试图为D语言做一些隐藏的营销(目前他正在使用它)......?

Andrei声称容器是可以的,但是迭代器很难看,非直观,容易出错并且很危险,很难实现(最后这个似乎是相当正确的......)我们在C ++中有什么用。 ..指针?他们不丑/ /危险吗?但我们高兴地拥抱他们并与他们一起生活。

哪一个更直观易懂:

for(auto i=foo.begin();i!=foo.end();++i)
    bar(*i);

for (auto r=foo.all(); !foo.empty(); foo.popFront())
        bar(r.front());

迭代器概念可以用范围和其他想法来补充,但我认为它们有它们的位置而且不会被替换。

答案 8 :(得分:1)

  1. 有时
  2. 可能
  3. 不太可能,至少不会多年

答案 9 :(得分:1)

与任何API或函数一样,如果误用可能会造成很多识别问题。 迭代器已用于许多项目,但始终根据其特性保持所需的必要护理。 在使用之前,应先充分了解其局限性。如果用户正确,迭代器可能非常有用 这个问题是相关的:
Is there any way to check if an iterator is valid?
Should I prefer iterators over const_iterators?

答案 10 :(得分:1)

我不同意Andrei和Konrad以及我自己: - )

最基本的概念是接口而不是迭代器,这在任何今天的任何工作中都非常明显(这是关于跨库,跨语言,交叉编译器,跨操作系统,跨平台,你交叉命名:-)

迭代器或范围(除了源级别使用)都不提供干净,简单,非侵入性或侵入性,非共享或共享,非唯一或唯一:指针!清除指向类型化数据的指针只是通用的,你可以使数据可变或不可变等许多其他东西。所有接口只是它的另一个间接层,同时仍然对各种机器和编译器友好,加上更安全,将迭代器和范围使用降级到实现细节。

在某种程度上,IEnumerable和IQueryable做了一半'正确的事'TM,但他们在迭代的概念上明显低劣,更多的是你可以用STL做什么,保留控制等等(但是,otoh,他们有更好的元数据,因此更好,更清洁的模型)。点对接口你可以构建你想要和满足的任何抽象,很可能是反对的,但实质上是一个明智的:最优的,运行时或编译时中立的数据表示和代码(对于算法和编译器和虚拟机而言至关重要) 。

甚至可以针对“动态”/组件系统进行优化,直至“运行时”内联(螺丝HotSpot VM :-) ..在这种程度上,1975年的进展很小,这可以从巨大的互操作行业工作量中看出来(它在你看的任何地方,包括这个网站,它使用专有和开放技术等;在计算机科学理想主义中,嗯,这种类型的接口'工作'应该不存在,如果它)...

答案 11 :(得分:0)

我认为C ++实现者将完全支持C ++ 0x,而无需实现新的非标准范例。

答案 12 :(得分:0)

我可以从该演示文稿中看到的唯一参数是无法定义范围,而c ++ 0x“语句范围”提议似乎在某种程度上消除了该问题。也许它不应该是关于是否应该/不应该使用迭代器的争论,而是更多应该/不应该使用它们的情况?