关于C ++迭代器的问题

时间:2016-07-01 00:54:46

标签: c++

在C ++中,为什么我们不能使用'>'或者'<&#;比较InputIterators,ForwardIterators和BidirectionalIterators?但是,我们可以将RandomAccessIterators与'>'进行比较。或者'<&#;;例如std :: vector。这背后的原因是什么?

另外,为什么我们不能讨论迭代器'内容?例如" cout<< itr<< ENDL;"不会工作。这背后的原因是什么?迭代器很像指针,但我们可以指出指针而不是迭代器,为什么?

一般来说,迭代器和指针之间的内在区别是什么?我曾经认为它们是相似的,但我想我必须理解这一点才能进入下一级理解c ++。

问题2:谢谢大家的精彩答案。关于迭代器,我还有一个问题。 为什么c ++打印出像" 50397953"当迭代器超出界限时?不应该打印像NULL或' \ 0' ?

3 个答案:

答案 0 :(得分:5)

std::list<T>具有双向迭代器,要求它们具有可比性并没有任何意义。甚至不清楚如何实现std::list<T>以符合这样的要求。但是,由于随机访问迭代器支持减法,很明显我们可以比较它们。

为什么我们不能打印迭代器的值?一般而言,作者是否支持此类操作。许多迭代器基本上只是作为指针或包装器的指针实现 - 为它们提供operator<<不会给用户带来任何好处,只需打印出指向的对象的地址就无法获得。

至于迭代器和指针之间的区别,指向对象的指针是一种特定的随机访问迭代器,但迭代器也可以是类类型,只要它们满足迭代器要求即可。

答案 1 :(得分:3)

既有严格的,正式的解释,也有实用的解释。

严格的正式解释

因为这就是它在C ++中的指定方式。

实际解释

根据定义,向量始终存储在连续的内存中。迭代器或多或少是一个指针。因此,通过比较实际的底层内存地址,可以定义哪个指针比另一个指针“更少”或“更大”。

另一方面,列表或集合中的每个元素都可以存储在任何地方。每个元素都是独立实例化的。列表中某个特定元素的迭代器可以引用数字较小的内存位置,而不是同一列表中另一个元素的不同迭代器,但实际元素可能位于实际列表中的另一个元素之后。如果列表中有两个迭代器,则无法立即确定哪个迭代器更接近列表的开头或结尾。请注意,在列表中插入和删除元素不会使现有列表迭代器无效,因为列表中的每个元素都是独立实例化的。

您不能在operator<<上使用std::ostream的迭代器的实际原因是因为当然没有定义此重载。请注意,您始终可以执行以下操作:

cout << &*itr << endl;

这将格式化引用元素的实际内存地址。但无论如何这都是可疑的。这几乎毫无意义。

答案 2 :(得分:1)

我不会回答你问题的第一部分,因为我同意所说的内容,但我会回答你的另外两部分,增加一些细节。我从最简单的部分开始解释。

  

一般来说,迭代器和指针之间的内在区别是什么?我曾经认为它们是相似的,但我想我必须理解这一点才能进入下一级理解c ++。

迭代器是指针的泛化。

您还可以查看iterator implementation on github

  

另外,为什么我们不能讨论迭代器的内容?例如“cout&lt;&lt; itr&lt;&lt; endl;”不行。这背后的原因是什么?迭代器很像指针,但我们可以指出指针而不是迭代器,为什么?

所以,据我所知,内部发生的事情是迭代器是一个具有存储指向项目的指针的字段的类。 '*'运算符被覆盖并返回存储在指针地址处的值。