C++ STL中的迭代器是什么?
在我的情况下,我正在使用一个list
,我不理解为什么你必须制定一个迭代器std::list <int>::const_iterator iElementLocator;
,然后通过取消引用运算符来显示列表的内容:
在将其分配给list.begin()
之后,cout << *iElementLocator;
.
请解释一下迭代器到底是什么以及为什么我需要对它进行解引用或使用它。
标准模板库(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
。这是算法接口假定的一部分,并且迭代器已经承诺遵守此接口。如果迭代器出现错误,没有遵守接口,那么编译器在调用类型为In
或Out
的函数时会生成错误。
我有点懒,所以不想描述迭代器是什么以及它们如何使用,尤其是当已经有很多在线文章可以自行阅读时。
以下是一些我可以引用的文章,提供完整文章的链接:
MSDN说:
顺便说一下,似乎MSDN从C++标准本身中取得了粗体文本,具体来说是从第§24.1/1节中取得的,该节说:迭代器是指针的一般化,以一种抽象的方式摆脱了指针的要求,使C++程序能够以统一的方式处理不同的数据结构。迭代器充当容器和通用算法之间的中介。算法被定义为在由迭代器类型指定的范围上操作,而不是在特定数据类型上操作。然后,任何满足迭代器要求的数据结构都可以被算法操作。有五种类型或类别的迭代器[...]
迭代器是指针的一般化,允许C++程序以统一的方式处理不同类型的数据结构(容器)。为了能够构造在不同类型的数据结构上正确高效地工作的模板算法,库不仅形式化了迭代器的接口,还形式化了其语义和复杂性假设。所有迭代器i支持表达式*i,产生某个类、枚举或内置类型T的值,称为迭代器的值类型。对于所有支持表达式(*i).m定义良好的迭代器i,支持表达式i->m,其语义与(*i).m相同。对于每种定义了等号的迭代器类型X,都有一种相应的带符号整数类型,称为迭代器的差异类型。
在C++中,迭代器是指向一些元素(例如数组或容器)中的某个元素的任何对象,具有使用一组运算符(至少是增量(++)和解引用(*)运算符)迭代该范围中的元素的能力。
最明显的迭代器形式是指针[...]
你也可以阅读这些文章:
耐心阅读所有内容,希望您有一些关于在C++中迭代器的概念。学习C++需要耐心和时间。
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
视为返回一个迭代器,该迭代器表示容器中最后一个位置之后的位置。迭代器是与STL容器相对应的指针。您可以将它们视为STL容器的指针对象。作为指针,您可以使用指针符号(例如*iElementLocator
,iElementLocator++
)。作为对象,它们将具有自己的属性和方法(http://www.cplusplus.com/reference/std/iterator)。
*
和 ->
可以表示任何东西。只有在此之后,你才应该去了解迭代器。否则,这可能会让你感到非常困惑。