迭代器的设计要点 《STL源码剖析》读书笔记
2011-09-08 14:28
295 查看
Slowing down your step,you will enjoy more ---wonderful
最初 对于迭代器的印象 是 迭代器能够访问容器中的元素,并对容器中的元素进行操作。实际上这也是作为容器使用者角度所看到的。
在阅读源码的过程中,越来越感觉到,迭代器的设计和容器应该说是没有直接的联系。真正和迭代器设计相关的是容器的节点,而不是容器的本身。
《STL源码剖析》中也提到 容器的本身和节点是不同的结构(如List本身和List节点结构不同)。 我们设计迭代器的时候更加应该关注容器节点,而不是容器。
下面以一个List 容器为例,
List 节点(node)结构:
template<class T>
struct __list_node{
typedef void* void_pointer;// void_pointer 现在表示空类型指针
void_pointer prev;// 型别为void* ,也可以定义为__list_node<T*>*类型
void_pointer next;
T data;
}
List容器的迭代器:
迭代器要求能够访问容器中的所有节点,并有能力进行一些其他的操作。因此设计迭代器就要研究节点的结构:
如果迭代器要访问节点的值 ,需要节点中的data,如下:
reference operator*() const { return (*node).data; }
如果迭代器要访问节点下一个节点 只需要获得节点中的next指针,如下:
self operator ++(){
node = (link_type)(*node).next;//定义时候为void* 所以这里要强制类型转换
return *this;
} 如果迭代器要访问节点前一个节点 只需要获得节点中的prev指针,如下:
实际上容器真正和迭代器关联起来,是通过把容器中的一个节点交给迭代器,然后迭代器就可以根据这个节点进行++,-- ,==,取值等操作,访问容器的其他节点。
如下:
// list.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int i;
list<int> ilist;
cout<<"size="<< ilist.size()<<endl;
ilist.push_back(0);
ilist.push_back(1);
ilist.push_back(2);
ilist.push_back(3);
cout<<"size="<< ilist.size()<<endl;
// 给迭代器初始化类型,让Template<class T> 中的 T 为 int
list<int>::iterator ite;
//下面注意了,这里给迭代器实例化,让迭代器指向容器中的一个节点。
//begin(),end() 函数就是用来取得容器中的一个节点的函数
//调用了迭代器中的 != ,++ ,*() 用来操作容器中节点
for(ite = ilist.begin();ite != ilist.end();++ite)
cout<< *ite<<' ';
cout<<endl;
return 0;
}
使用迭代器的时候: 先让迭代器知道容器持有对象的类型
list<int>::iterator ite; //持有int
然后让迭代器指向容器中的一个节点:和容器联系真正的开始
ite = ilist.begin();//迭代器获得容器中的一个节点
最后调用迭代器中已经定义好的一些操作,就可以操作容器了。
最初 对于迭代器的印象 是 迭代器能够访问容器中的元素,并对容器中的元素进行操作。实际上这也是作为容器使用者角度所看到的。
在阅读源码的过程中,越来越感觉到,迭代器的设计和容器应该说是没有直接的联系。真正和迭代器设计相关的是容器的节点,而不是容器的本身。
《STL源码剖析》中也提到 容器的本身和节点是不同的结构(如List本身和List节点结构不同)。 我们设计迭代器的时候更加应该关注容器节点,而不是容器。
下面以一个List 容器为例,
List 节点(node)结构:
template<class T>
struct __list_node{
typedef void* void_pointer;// void_pointer 现在表示空类型指针
void_pointer prev;// 型别为void* ,也可以定义为__list_node<T*>*类型
void_pointer next;
T data;
}
List容器的迭代器:
迭代器要求能够访问容器中的所有节点,并有能力进行一些其他的操作。因此设计迭代器就要研究节点的结构:
如果迭代器要访问节点的值 ,需要节点中的data,如下:
reference operator*() const { return (*node).data; }
如果迭代器要访问节点下一个节点 只需要获得节点中的next指针,如下:
self operator ++(){
node = (link_type)(*node).next;//定义时候为void* 所以这里要强制类型转换
return *this;
} 如果迭代器要访问节点前一个节点 只需要获得节点中的prev指针,如下:
self operator --(){ node = (link_type)(*node).prev;//定义时候为void* 所以这里要强制类型转换 return *this; }上面代码的实现,都只需要研究节点的结构就可以做到。而无需关心容器是怎么实现。
实际上容器真正和迭代器关联起来,是通过把容器中的一个节点交给迭代器,然后迭代器就可以根据这个节点进行++,-- ,==,取值等操作,访问容器的其他节点。
如下:
// list.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int i;
list<int> ilist;
cout<<"size="<< ilist.size()<<endl;
ilist.push_back(0);
ilist.push_back(1);
ilist.push_back(2);
ilist.push_back(3);
cout<<"size="<< ilist.size()<<endl;
// 给迭代器初始化类型,让Template<class T> 中的 T 为 int
list<int>::iterator ite;
//下面注意了,这里给迭代器实例化,让迭代器指向容器中的一个节点。
//begin(),end() 函数就是用来取得容器中的一个节点的函数
//调用了迭代器中的 != ,++ ,*() 用来操作容器中节点
for(ite = ilist.begin();ite != ilist.end();++ite)
cout<< *ite<<' ';
cout<<endl;
return 0;
}
使用迭代器的时候: 先让迭代器知道容器持有对象的类型
list<int>::iterator ite; //持有int
然后让迭代器指向容器中的一个节点:和容器联系真正的开始
ite = ilist.begin();//迭代器获得容器中的一个节点
最后调用迭代器中已经定义好的一些操作,就可以操作容器了。
相关文章推荐
- STL源码剖析_读书笔记:第三章 迭代器概念与traits编程技法
- 《STL源码剖析》读书笔记------第3 章 迭代器概念与traits编程技法
- 多线程设计要点
- ASP网页设计要点-记录
- 【游戏设计】游戏设计师修炼秘籍 读书笔记四 (针对IOS智力类型游戏设计)
- (深入探讨线程设计)以及MsgWaitForMultipleObjects函数的使用要点
- C++设计模式之十六:Iterator 迭代器
- 《Effective C++第三版》读书笔记——设计与声明
- 网站设计要点
- 设计模式-- 读书笔记(一)
- 『重构--改善既有代码的设计』读书笔记----代码坏味道【1】
- FPGA学习(第4节)-FPGA设计中的规则技巧要点及常见语法(重要)
- 多线程设计要点
- Java读书笔记12 事件处理基础 Observer设计模式
- Hadoop分布式文件系统:架构和设计要点
- 《STL源码剖析》读书笔记--第二章 空间配置器(allocator)
- STL源码剖析 笔记之三 迭代器
- Java:设计与使用迭代器 推荐
- HeadFirst 设计模 4000 式 9迭代器与组合模式(餐厅合并)
- 硬件工程师电路设计必须紧记的十大要点