前言
"打牢基础,万事不愁" .C++的基础语法的学习
引入
C++基础:STL概述-CSDN博客 上一篇梳理了一些同STL有关的概念.同时对理解迭代器需要的类包含,内部类,链表等内容做了分析,这篇从<C++ Prime Plus> 6th Edition(以下称"本书")的P684,大标题16.4泛型编程开始,看迭代器的内容
迭代器内容概述
"16.4.1为何使用迭代器"这一节,内容非常好,但是不看源码不好懂.内容好的原因是作者讲了迭代器的设计思路,真正是"自顶向下设计".(如果设计者能做到这样先有思路,再有概念设计,再到具体实现,必定是不差).
"16.4.2迭代器类型"这一节有表16.3---随机访问迭代器操作,"16.4.3迭代器的层次结构"有表16.4---迭代器性能,内容比较简单,仔细看就明白了:迭代器功能<=指针功能.指针有的运算,比如p++,p--,++p,--p,p[],p+n,p-n等等,每种不同的迭代器或者有一部分,或者全有(随机访问迭代器就是全都有).他说明了迭代器的用法和指针基本一致.
"16.4.4概念、改进和模型"这一节的内容更加抽象,讲的是迭代器在算法上的应用,举了个例子copy()函数,是以迭代器的方式实现的(本书P691第三段).还讲了另外几种迭代器,反向迭代器reverse_iterator的用法,back_insert_iterator,front_insert_iterator和inset_iterator的用法.
这部分内容在学完以后也可以反复揣摩.
迭代器的推导
迭代器的定义只有一句话:迭代器是广义指针.
本书P685第三段:"迭代器使算法独立于使用的容器类型".下面举了指针遍历数组和链表的例子.
P685倒数第二段,函数不仅独立于容器中存储的数据类型,而且独立于容器本身的数据结构.模板提供了存储在容器中的数据类型的通用表示,因此还需要遍历容器中的值的通用表示,迭代器正是这样的通用表示.
1>迭代器的设计思想
迭代器要实现哪些功能?本书P686,打黑点的4个段落有说,和指针基本上一致.
容器内部遍历数据是很容易的.在设计容器属性时,包含了"物理容器",以及和物理容器相关的各项属性.不管是数组还是链表做底层,用for还是while,使用指针遍历容器内数据不难办到.那么如何采用一种让所有容器都适用的方法去遍历每个容器的数据呢?对此进行了概念设计,
2>迭代器概念设计:
本书P687中间以"STL遵循上面介绍的方法"开始那一段:每个容器类定义了相应的迭代器类型.每个容器类都有一个超尾标记,当迭代器递增到超越容器最后一个值后,这个值将被赋给迭代器;每个容器类都有begin()和end()方法,他们分别返回一个指向容器的第一个元素和超尾位置的迭代器.每个容器类都使用++操作,让迭代器逐步指向超尾位置,从而遍历容器类的每一个元素.
以上是设计迭代器时对容器的要求.特别颜色的"容器类"是翻译错误,应为"迭代器类"
解读:每个容器类定义了迭代器类型,说明迭代器是一个容器和容器相关的类,迭代器能访问容器里的数据,采用类包含把容器内的数据添加进来,形成对数据的访问和修改.并且因为只和容器相关,所以他是容器的内部类.
迭代器图示如下:
----说明:1.容器里的数据被迭代器类包含,获得访问或修改的权限.
2.迭代器生成对象first,修改属性值,使指针指向数据首元素;再生成对象last,修改属性值,使指针指向超尾.超尾的意思:对于数组而言是最大元素个数,对链表而言是0(nullptr),表示指针指空.定义迭代器函数++,使属性值从头指向尾部.
3.迭代器和容器交互, 由函数返回刚生成的对象.
迭代器的意思是本来由容器可完成的遍历交给内部类迭代器去完成
3>迭代器的实现
本书P687中间段落,以"使用容器类时"开始,无需知道其迭代器如何实现的,也无需知道超尾是如何实现的,而只需知道他有迭代器,其begin()返回一个指向第一个元素的迭代器,end()返回一个指向超尾位置的迭代器即可
本着探索精神,参照黑皮书尝试了自己写个迭代器,结果不行,某些函数被禁止重新定义
=============================内容分割线====================================
以下代码不可用
///*未成功代码,原因未知,待发掘*/
//#include<iostream>
//using namespace std;
//
//template<class T>
//class Container {
// enum { MAX = 10 };
// int length;
// T a[MAX];
//public:
// Container(int len):length(len);
// class Iterator {
// public:
// T* container;
// int leng;
// Iterator(T* outobject, int len = 0) :container(outobject), leng(len) {}
// Iterator operator++() {
// this->leng++;
// return Iterator(a, leng);
// }
// T operator*() {
// return container[leng];
// }
// bool operator!=(Iterator& it) {
// return this->leng != it->leng;
// }
// };
// Iterator begin() const { return Iterator(a, 0) }; //报错:未知重写说明符begin
// Iterator end() const { return Iterator(a, length) }; //报错:未知重写说明符end
//};
//
//int main(void) {
// Container<double> tmp(5);
// for (auto it = tmp.begin(); it != tmp.end(); it++) { //it无法初始化,找不到匹配的!=运算符,
// cout << *it << endl; //*非法间接寻址,<<对于class非法
// }
//}
//
=============================内容分割线====================================
书上的意思很明了,只要知道怎么用就行了.也就是说编译器把他固定成不能修改的模块了.
迭代器类型和迭代器的层次结构
这两小节的内容比较简单.意思是容器类被分类成若干类,每个类对应的迭代器功能有差别,其中随机迭代器功能最多,完全等于指针.其他类的迭代器功能少于指针功能. 到了用的时候,查表就行了.
概念、改进和模型
这一节讲了几个迭代器的用法,大概看一看,到时候查
小结
迭代器内容的理解