【STL】深入STL,泛型编程,为何要使用迭代器??

        我们现在了解STL怎么使用后,再了解了解STL的底层原理,他使用了泛型编程,面向对象编程关注的是编程的数据方面的,而泛型编程关注的是算法,旨在编写出独立于数据类型的代码。

为什么要使用迭代器,理解迭代器就是理解STL的关键所在。模板使得算法独立于存储的数据类型,而迭代器使得算法独立于使用的容器类型。

我们先来看看为两种数据结构表示的find函数,

int *find(int *arr, int n, const int &tar)
{	
​	for(int i = 0; i < n; i++)
{
​	if(arr[i] == tar)
​	return &arr[i];
    }
    return nullptr;
}

find()函数在数组中找到等于tar的值,则返回该值在数组中的地址,否则返回一个空指针,可以使用模范将这种查找算法推广到包含==运算符的、任意类型的数组。

下面我们看看另一种数据结构——链表的查找算法,链表是链接在一起的Node结构组成:

struct Node
{
	int val;
	Node *p_next;
};

假设有一个指向链表头结点的一个指针,每个结点的p_next都指向下一个结点,链表最后一个结点的p_next指向nullptr,那么链表的find函数可以这样写,

Node *findl(Node *head, const int &tar)
{
	Node *tur;
	for(tur = head; tur != nullptr; tur = tur->next)
	{
		if(tur->val = tar)
		return tur;
	}
	return nullptr;
}

从实现细节上看,这两个find函数是不同的,一个使用数组索引来遍历整个数组,另一个是tur = tur->next,但广义上来说,这两种算法是相同的,都是将值与容器中每个元素进行比较,找到一样的为止。

泛型编程的目的是使用同一个find函数来处理数组,链表,或者任何其他的容器类型。

而函数不仅独立于容器中存储的数据类型,而且独立于容器本身的数据结构,模板可以提供存储在容器中数据类型的通用表示,所以,我们还需要一个遍历容器中的值的通用表示,而迭代器正式这样的通用表示。

我们来想想,要实现一个find函数,迭代器要具备哪些特征呢?

  • 能够对迭代器执行解除引用操作,以便能够访问它引用的值,
  • 能够将一个迭代器赋值给另一个,如果p。q都是迭代器,应对p=q进行定义
  • 能够将一个迭代器和另一个迭代器进行比较,看他们是否相等
  • 能够使用迭代器遍历容器中所有的元素定义++p和p++

常规指针就能满是迭代器的需求,那么find函数的代码就可以这样写, 

typedef int *iterator;
iterator find(iterator begin, iterator end, const int &tar)
{
    iterator ar;
    for(ar = begin; ar != end; ar++)
    {
        if(*ar == tar)
            return ar;
    }
    return nullptr;
}

对于链表的find函数,可以定义一个迭代器类,其中定义了运算符*和++,

struct Node
{
    int val;
    Node* p_next;
};

class iterator
{
    Node* pt;
public:
    iterator() : pt(0){}
    iterator (Node *pn) : pt(pn) {}
    int operator*(){}
    iterator& operator++(){}
        
    //...operator ==(){}    operator !=(){}
};

这样,有了这样一个iterator类后,第二个find函数就可以这样写,

iterator find(iterator head, const int &tar)
{
    iterator ar;
    for(ar = head; ar != nullptr; ar++)
    {
        if(*ar == tar)
            return ar;
    }
    return nullptr;
}

​

这和第一个find()函数几乎相同

差别在于如何确定是否达到最后一个值,第一个使用了超尾迭代器,而第二个是最后一个指针指向空指针,除了这一点小差别以外这两个函数完全相同,如果让链表的后面再加一个元素,即让链表和数组都超尾,这样两个的代码将完全相同。

总结:

STL遵循上面的方法,首先,每个容器类定义了相应的迭代器类型。对与其中的某个类,迭代器可能是指针;而对于另一个类,迭代器可能是一个对象。

就是这样,假设有8个容器类,需要支持10种操作,如果每个类都有自己的成员函数,则需要定义8*10个成员函数,而STL方式,只需要定义10个非成员函数即可,使用泛型编程,不同的容器,不同的数据类型,不同的数据结构,只需要使用这些函数就能来执行查找、排序等操作。

有时候,即使有执行相同任务的非成员函数,STL有时会定义一个成员函数。这是因为对有些操作,类特定算法比通用算法效率高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值