这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
STL迭代器
光看迭代器的一些例子,会觉得不难理解,是基于指针的一种设计。不过STL迭代器有着更重要的意义。在C++ Premier Plus中,这样描述STL:STL是泛型编程(generic programming)的典范,泛型编程即多种数据类型在同一种算法或者结构上皆可操作,其效率与针对某特定数据类型而设计的算法或者结构相同。这种编程范式能够在编译期间确定数据类型,充分发挥编译器的能力,使运行时更高效。
而STL迭代器是理解STL哲学的核心,比如说对于两种不同的container:array和list,实现在这两个数据结构中寻找某个特定元素显而易见需要不同的方式:
// array查找
double * find_ar(double * ar, int n, const double & val)
{
for (int i = 0; i < n; i++)
if (ar[i] == val)
return &ar[i];
return 0;
}
// Node数据结构
struct Node {
double item;
Node * p_next;
};
// Node查找
Node* find_ll(Node * head, const double & val)
{
Node * start;
for (start = head; start!= 0; start = start->p_next)
if (start->item == val)
return start;
return 0;
}
这样对各种数据结构去实现不同的方法效率不高,而且维护起来难,而如果像下面去定义一个iterator类,并对自增操作符(包括i++与++i)做一个重载,就可以达到用一个函数去处理两种不同的数据结构的效果。
class iterator {
Node * pt;
public:
iterator() : pt(0) {}
iterator (Node * pn) : pt(pn) {}
double operator*() { return pt->item;}
iterator& operator++()
{
pt = pt->p_next;
return *this;
}
iterator operator++(int)
{
iterator tmp = *this;
pt = pt->p_next;
return tmp;
}
}
// 通用的find函数,传入一个iterator
iterator find_ll(iterator head, const double & val) {
iterator start;
for (start = head; start!= 0; ++start)
if (*start == val)
return start;
return 0;
}
对于STL中不同的container,都有定义对应的iterator,使得STL的algorithm能在不同的container上达到相同的目的。而且值得一提的是,这种做法并没有去重载container的操作符,将这种逻辑与container解耦了。当然,对于基本的指针类型转换为iterator涉及一些处理,包含了更多的技巧,详见这里。