2011-04-09 52 views
5

嗨所以我对于迭代器有点迷茫,他们实际上是....在C++ STL了解迭代

在这种情况下即时通讯使用的名单,我不明白为什么你有什么做一个迭代器:
std::list <int>::const_iterator iElementLocator;

由derefrence运营商dipslay列表的内容:
cout << *iElementLocator;

赋予它也许list.begin后();

请解释什么是一个迭代器,为什么我必须去除它/使用它!
谢谢!

回答

10

有在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()算法作为参数模板的类型InOut类型的一个迭代两个迭代。它将从位置first开始并在位置last之前结束的元素复制到res中。算法知道获得下一个元素需要说++first++res。它知道要读取一个元素,它需要说x = *first并写一个元素,它需要说*res = x。这是接口算法假设和迭代器承诺的一部分。如果错误的迭代器不符合接口,那么当类型未定义函数时,编译器将通过类型InOut发出调用函数的错误。

+0

+1很好的解释。 – Nawaz 2011-04-09 19:29:03

0

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

一个example

如果有什么具体的东西你不明白回来问。

+5

堆栈溢出问题经常成为谷歌的热门话题,此时回答说:“为什么不谷歌呢”看起来相当短视。 http://meta.stackexchange.com/questions/5280/embrace-the-non-googlers – 2011-04-09 18:39:20

6

我很懒。因此,我不会键入描述什么是迭代器以及它们是如何使用的,尤其是当已经有很多在线文章可供您阅读时。

这里有一些,我可以引述一开始,proividing的链接来完成的文章:

MSDN说,

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

顺便说一句,似乎MSDN采取了文本加粗从C++标准本身,特别是从部分§24.1/ 1,它说:

迭代是 指针,其允许C++程序与以均匀的方式不同的数据结构 (容器) 工作的概括。为了 能够构建模板 算法正确 有效地工作在不同类型的数据 结构,图书馆正式确定不 只是接口也是 语义和复杂的假设迭代 。所有迭代器我支持 表达式* i,导致某个类,枚举或 内置类型T的值为 ,称为迭代器的值类型 。所有用于 的迭代器i其表达式(* i).m为 ,定义明确,支持表达式 i-> m,其语义与 (* i).m相同。对于 的每个迭代类型X,定义了相等性,将有一个 对应的有符号整数类型 ,称为 迭代器的差异类型。

cplusplus说,

在C++中,一个迭代是任何对象 的是,指向一些元件在 范围的元素(如数组或 的容器)的,有能力到 使用一组运算符(至少为 ,增量(++)和 解除引用(*)运算符)遍历该 范围的元素。

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

而且你还可以阅读这些:

请耐心等待并阅读所有这些内容。希望你在C++中能够知道迭代器是什么。学习C++需要耐心和时间。

0

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

2

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

1

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

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

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

您可能决定允许集合记住“当前”项目。它可以像startmorenext功能,让您可以遍历内容:

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++中)要注意的一个重点是它们可能会失效。例如,如果您清空容器,通常会发生这种情况:指向该容器中位置的任何迭代器现在都变得无效。在那个状态下,他们的大部分操作都是未定义的 - 任何事情都可能发生!