了解STL中的迭代器

时间:2011-04-09 18:28:05

标签: c++ stl iterator

嗨,所以我对迭代器以及它们实际上是什么有点困惑....在C ++ STL中

在这种情况下我使用列表,我不明白你为什么要做一个迭代器:
std::list <int>::const_iterator iElementLocator;

由derefrence运算符dipslay列表的内容:
cout << *iElementLocator;

将其分配给list.begin();

请解释一下迭代器的确切含义以及为什么我必须解除它/使用它! 的谢谢!

6 个答案:

答案 0 :(得分:18)

STL中有三个构建块:

  • 容器
  • 算法
  • 迭代

在概念层面,容器保存数据。这本身并不是很有用,因为你想要一些数据;你想要操作,操纵它,查询它,玩它。算法就是这样做的。但算法不持有数据,没有数据 - 他们需要一个容器来完成此任务。为容器提供一个容器,然后你就可以继续操作了。

从技术角度来看,唯一需要解决的问题是算法如何遍历容器。从技术上讲,容器可以是链表,也可以是数组,二叉树或任何其他可以保存数据的数据结构。但遍历数组与遍历二叉树的方式不同。尽管概念上所有算法都希望从容器中一次“获取”一个元素,然后处理该元素,但从容器中获取下一个元素的操作在技术上是非常容器的 - 具体

看起来好像你需要为每个容器编写相同的算法,因此每个版本的算法都有正确的代码来遍历容器。但是有一个更好的解决方案:让容器返回一个可以遍历容器的对象。该对象将具有已知的接口算法。当算法要求对象“获取下一个元素”时,对象将遵守。因为对象直接来自容器,所以它知道如何访问容器的数据。并且因为该对象具有算法所知的接口,所以我们不需要为每个容器复制算法。

这是迭代器。

这里的迭代器将算法粘合到容器,而不将两者耦合。迭代器耦合到容器,算法耦合到迭代器的接口。这里魔术的来源实际上是模板编程。考虑标准的copy()算法:

template<class In, class Out>
Out copy(In first, In last, Out res)
{
    while( first != last ) {
        *res = *first;
        ++first;
        ++res;
    }
    return res;
}

copy()算法将类型In上模板化的两个迭代器和Out类型的一个迭代器作为参数。它会将位置从first开始并在位置last之前结束的元素复制到res。该算法知道要获得下一个元素,它需要说++first++res。它知道要读取一个元素,它需要说x = *first并写一个元素,它需要说*res = x。这是接口算法假设和迭代器提交的一部分。如果错误的迭代器不符合接口,那么当类型没有定义函数时,编译器会发出错误以调用类型InOut上的函数。

答案 1 :(得分:6)

我很懒。所以我不打算描述迭代器是什么以及它们是如何被使用的,特别是当你已经有很多在线文章可以自己阅读时。

这里有一些我可以引用的开头,可以提供完整文章的链接:

MSDN说,

  

迭代器是一种概括   指针,从他们的抽象   要求以允许的方式   与不同的C ++程序一起工作   数据结构统一。   迭代器充当中介   容器和通用之间   算法。而不是操作   具体的数据类型,算法都是   定义为在一个范围内操作   由迭代器类型指定。任何   满足的数据结构   然后可能需要迭代器   由算法操作。那里   是五种类型或类别   迭代器[...]

顺便说一下,似乎MSDN已经从C ++标准本身采用粗体文本,特别是来自§24.1/ 1的部分

  

迭代器是一种概括   允许C + +程序的指针   使用不同的数据结构   (容器)以统一的方式。 To   能够构建模板   正确运行的算法   有效地处理不同类型的数据   结构,图书馆没有形式化   只是接口而且还有   语义和复杂性假设   迭代器。我支持的所有迭代器   表达式* i,导致a   某些类的值,枚举或   内置类型T,称为值类型   迭代器。所有迭代器我都是   其中表达式(* i).m是   定义明确,支持表达   i-&gt; m具有与之相同的语义   (* I).M。对于每个迭代器类型X for   哪个等式定义,有一个   相应的有符号整数型   称为差异类型   迭代器。

cplusplus说,

  

在C ++中,迭代器是任何对象   那,指向一个元素   元素范围(例如数组或   一个容器),有能力   遍历那些元素   范围使用一组运算符(at   至少,增量(++)和   dereference(*)operator)。

     

最明显的迭代器形式是   指针[...]

你也可以阅读这些:

有耐心并阅读所有这些。希望您能在C ++中了解迭代器是什么。学习C ++需要耐心和时间。

答案 2 :(得分:2)

迭代器是指向STL容器的指针指向数组的内容。您可以将它们视为STL容器的指针对象。作为指针,您将能够使用指针表示法(例如*iElementLocatoriElementLocator++)。作为对象,它们将具有自己的属性和方法(http://www.cplusplus.com/reference/std/iterator)。

答案 3 :(得分:2)

迭代器与容器本身不同。迭代器引用容器中的单个项目,并提供到达其他项目的方法。

考虑在没有迭代器的情况下设计自己的容器。它可以有一个size函数来获取它包含的项目数,并且可以使[]运算符超载,以允许您根据其位置获取或设置项目。

但是那种“随机访问”并不容易在某些容器上有效实现。如果您获得了第一百万项:c[1000000]并且容器内部使用链接列表,则必须扫描一百万个项目才能找到您想要的项目。

您可能会决定允许集合记住“当前”项目。它可以包含startmore以及next等功能,以便您遍历内容:

c.start();
while (c.more()) 
{
    item_t item = c.next();

    // use the item somehow
}

但是这会将“迭代状态”置于容器内。这是一个严重的限制。如果您想将容器中的每个项目与其他项目进行比较,该怎么办?这需要两个嵌套循环,都遍历所有项目。如果容器本身存储迭代的位置,则无法嵌套两个这样的迭代 - 内部循环将破坏外部循环的工作。

因此迭代器是迭代状态的独立副本。您可以开始迭代:

container_t::iterator i = c.begin();

迭代器i是一个单独的对象,表示容器中的位置。您可以获取存储在该位置的任何内容:

item_t item = *i;

您可以转到下一个项目:

i++;

使用一些迭代器,您可以跳过几个项目:

i += 1000;

或者在相对于迭代器标识的位置的某个位置获取项目:

item_t item = i[1000];

使用一些迭代器,你可以向后移动。

通过将迭代器与end进行比较,您可以发现是否超出了容器的内容:

while (i != c.end())

您可以将end视为返回一个迭代器,该迭代器表示超出容器中最后一个位置的位置。

使用迭代器(以及通常在C ++中)注意的一个重点是它们可能变得无效。例如,如果清空容器,通常会发生这种情况:指向该容器中位置的任何迭代器现在都变为无效。在那种状态下,对它们的大多数操作都是未定义的 - 任何事情都可能发生!

答案 4 :(得分:0)

已经存在很多关于迭代器的好解释。只是谷歌吧。

一个example

如果有某些特定的东西,你不理解回来问。

答案 5 :(得分:0)

我建议在C ++中阅读有关运算符重载的内容。这将说明为什么*->基本上可以表示任何内容。只有这样你才能阅读迭代器。否则它可能看起来很混乱。