《STL源码剖析》学习笔记-第3章 迭代器
来源:互联网 发布:网站关键词优化方法 编辑:程序博客网 时间:2024/06/03 17:56
1、迭代器设计思维-STL关键所在
迭代器:就是提供一种方法,在不需要暴露某个容器的内部表现形式情况下,使之能依次访问该容器中的各个元素。
STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此独立设计,最后再以一帖粘合剂将它们撮合在一起。只要对算法给予不同的迭代器,就可以对不同容器进行相同的操作。
以算法find( )为例,它接受2个迭代器和1个”搜寻目标”:
// 摘自SGI <stl_algo.h>template <class InputIterator, class T>InputIterator find(InputIterator first,InputIterator last,const T& value){ while (first != last && *first != value) ++first; return first;}
只要给予不同的迭代器,find()便能够对不同的容器进行查找操作:
#include <vector>#include <list>#include <deque>#include <algorithm>#include <iostream>using namespace std;int main(){ const int arraySize = 7; int ia[arraySize] = { 0,1,2,3,4,5,6 }; vector<int> ivect(ia, ia+arraySize); list<int> ilist(ia, ia+arraySize); deque<int> ideque(ia, ia+arraySize); vector<int>::iterator it1 = find(ivect.begin(), ivect.end(), 4); if (it1 == ivect.end()) cout << "4 not found." << endl; else // 結果:4 found. 4 cout << "4 found. " << *it1 << endl; list<int>::iterator it2 = find(ilist.begin(), ilist.end(), 6); if (it2 == ilist.end()) cout << "6 not found." << endl; else// 結果:6 found. 6 cout << "6 found. " << *it2 << endl; deque<int>::iterator it3 = find(ideque.begin(), ideque.end(), 8); if (it3 == ideque.end()) cout << "8 not found." << endl; else// 結果:8 not found. cout << "8 found. " << *it3 << endl; return 0;}
2、迭代器是一种智能指针
迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的便是内容提领(dereference)和成员访问(member access),因此,迭代器最重要的编程工作就是对 operator*
和 operator->
进行重载(overloading)工作。
使得所有实现细节得以封装起来,不被使用者看到,是每一种STL容器都提供有专属迭代器的缘故。
3、Traits编程技法——STL源代码门钥
迭代器所指对象的型别,称为迭代器的value type。
我们知道:
(1)通过函数模板的参数类型推导解决函数体内声明变量的问题
(2)进一步,函数模板的参数类型推导推而导之的只是参数,无法推导函数的返回值型别。这时,如果需要返回类型是迭代器所指对象的类型,解决办法就是内嵌类型声明,即在迭代器内部添加一种“特性”,通过这种“特性”,算法可以很容易地获知迭代器所指对象的类型。
但是,问题来了,并不是所有迭代器都是class type。原生指针是迭代器,但它不是一种类类型,无法定义内嵌类型。怎么办?针对原生指针做特殊化的处理,利用模板偏特化就可以做到了。
利用模板偏特化解决原生指针不能内嵌类型的问题,iterator_traits就是关键。
在STL实现中,traits编程技术利用了“内嵌类型”的编程技巧与C++的template参数推导功能,弥补了C++类型识别方面的不足。通过traits,算法可以原汁原味的将迭代器的属性萃取出来,帮助算法正确高效的运行。
所谓traits,其意义是,如果template <class I>
中的I定义有自己的value type,那么通过这个traits的作用,萃取出来的value_type就是I::value_type
。traits就像一台”特性萃取机”,萃取出各个迭代器的特性。
4、迭代器基本框架
最常用到的迭代器相应型别有五类:value type, difference type, pointer, reference, iterator catagoly
。
STL提供的iterator class如下。它不含任何成员,纯粹只是型别定义。
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&>struct iterator { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference;};
特性萃取机traits会很原汁原味的榨取出来:
template <class I>struct iterator_traits { typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename I::difference_type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference;};
这些类型所表示的意义如下:
value type 表示迭代器所指对象的型别;difference type 表示两个迭代器之间的距离;也可表示一个容器最大容量reference 为引用类型;pointer 为指针类型;iterator_category 表明迭代器的类型;
根据迭代器移动特性与施行动作,迭代器被分为五类:
1、Input Iterator:这种迭代器所指对象,不允许外界改变,只读(read only);2、Output Iterator:唯写(write only);3、Forward Iterator:允许「写入型」算法(例如 replace())在此种迭代器所形成的区间上做读写动作;4、Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间(例如逆向拷贝某范围内的元素),就可以使用 Bidirectional Iterators;5、Random Access Iterator:前四种迭代器都只供应一部份指标算术能力(前3种支持 operator++ ,第4种再加上 operator--),第5种则涵盖所有指标算术能力,包括 p+n, p-n, p[n], p1-p2, p1<p2.
- 《STL源码剖析》学习笔记-第3章 迭代器
- 《STL源码剖析》学习笔记之一 迭代器
- 《STL源码剖析学习笔记》
- 《STL源码剖析》学习笔记
- 侯捷《STL源码剖析》--STL学习笔记
- 《STL源码剖析》学习笔记-第2章 空间配置器
- 《STL源码剖析》学习笔记-第4章 序列式容器
- 《STL源码剖析》学习笔记-第4章 序列式容器(二)
- 《STL源码剖析》学习笔记-第5章 关联式容器
- 《STL源码剖析》学习笔记-第5章 关联式容器(二)
- 《STL源码剖析》学习笔记-第6章(一) set相关算法
- STL学习笔记之迭代器--iterator(源码剖析)
- stl源码剖析 详细学习笔记deque(3)
- stl源码剖析 详细学习笔记 算法(3)
- STL源码剖析:vector学习笔记
- stl源码剖析 详细学习笔记heap
- stl源码剖析 详细学习笔记 hashtable
- stl源码剖析 详细学习笔记 配接器
- linux重定向输出
- 专题三 第十题
- 双向链表 删除某个节点
- mysql之视图详解
- spring mvc 与struts2比较
- 《STL源码剖析》学习笔记-第3章 迭代器
- 详细介绍ASP.NET页面间数据传递的使用方法
- js中return false(阻止)的用法
- linux上tomcat环境搭建
- Android模拟器检测常用方法
- 69道Spring面试题和答案
- C++作业5
- linux常用命令
- DVBS/S2在数字电视系统中的应用