STL源码剖析:迭代器
准备知识
什么是迭代器?
迭代器是链接容器和算法的桥梁,所有的算法都通过迭代器操作容器中的数据
迭代器是一种智能指针,最重要的操作符重载就是
operator*,operator->迭代器的实现需要知道容器的具体细节,因此每一种容器都对应自己特有的迭代器,但是迭代器的接口是一致的
Traits编程技巧
目的:提取出容器中存放的数据类型
核心是使用模板技术,在编译期就确认需要调用的函数
嵌套从属名称:
template <typename T>
class Data
{
typedef T value_type;
}; template <typename T>
class Type
{
// typename T::value_type 就是一个嵌套从属名称,其中的typename不能掉
// 理解模板类型中使用模板类型
typedef typename T::value_type value_type;
}; int main()
{
Type<Data<int>>::value_type a(); // a()表示一个类型为int的变量
}
占位参数实现函数重载
占位参数是函数参数,只是这种参数只有参数类型,没有参数名
占位参数同样属于参数列表,可以实现重载
// int是占位参数
void print(int)
{
cout << "void print(int)" << endl;
} void print()
{
cout << "void print()" << endl;
} int main()
{
print(); // 调用void print(int)
print(); // 调用void print()
}
源码
常用的迭代器相应类型
一般在迭代器中常用的容器类型一共5种
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:与reference对应的指针类型
iterator_category:
Input Iterator:只读
Output Iterator:只写
Forward Iterator:可读可写,只能前进,每次前进一个单位
Bidirectional Iterator:可读可写,双向移动,每次移动一个单位
Random Access Iterator:可读可写,双向移动,每次移动多个单位
*/
- 由于原生的指针类型并没有提供者5种类型的定义,因此进行特化处理
// 实现原生指针的类型提取
template <class T>
struct iterator_traits<T*>
{
...
typedef T* pointer;
typedef T& reference;
}; // 实现const指针的类型提取,去掉const属性,因为会通过迭代器操作容器中的数据
template <class T>
struct iterator_traits<const T*>
{
...
typedef const T* pointer;
typedef const T& reference;
};
- 5种iterator_category的类型定义,都只是类型定义,没有任何成员
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag : public input_iterator_tag { };
struct bidirectional_iterator_tag : public forward_iterator_tag { };
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
iterator完整代码
迭代器类型相关代码
// 五种迭代器类型
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {}; // 定义一个基础类,提供迭代器需要的类型定义,编译继承实现,防止遗漏
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;
}; // 类型提取
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type
typedef typename Iterator::difference_type
typedef typename Iterator::pointer
typedef typename Iterator::reference
}; // 针对原生指针的特化处理
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
}; // 针对const指针的特化处理
template <class T>
struct iterator_traits<const T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
}; // 该函数非常方便的提取某个迭代器的类型iterator_category
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category iterator_category(const Iterator&)
{
typedef typename iterator_traits<Iterator>::iterator_category category;
return category();
} // 该函数非常方便的提取某个迭代器的类型difference_type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type* distance_type(const Iterator&)
{
return static_cast<typename iterator_traits<Iterator>::difference_type*>();
} // 该函数非常方便的提取某个迭代器的类型value_type
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type* value_type(const Iterator&)
{
return static_cast<typename iterator_traits<Iterator>::value_type*>();
}
- advance函数
// 迭代器前进
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n)
{
__advance(i, n, iterator_category(i));
} // radom迭代器前进
template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag)
{
i += n;
} // bidirectional迭代器前进
template <class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag)
{
if (n >= )
while (n--) ++i;
else
while (n++) --i;
} // input迭代器前进
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag)
{
while (n--) ++i;
}
- distance函数
// 计算迭代器之间的距离
template <class InputIterator>
inline iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last)
{
typedef typename iterator_traits<InputIterator>::iterator_category category;
return __distance(first, last, category());
} // 计算random迭代器之间的距离
template <class RandomAccessIterator>
inline iterator_traits<RandomAccessIterator>::difference_type __distance(RandomAccessIterator first, RandomAccessIterator last,
random_access_iterator_tag)
{
return last - first;
} // 计算Input迭代器的距离
template <class InputIterator>
inline iterator_traits<InputIterator>::difference_type __distance(InputIterator first, InputIterator last, input_iterator_tag)
{
iterator_traits<InputIterator>::difference_type n = ;
while (first != last)
{
++first;
++n;
}
return n;
}
- __type_traits技术
不属于标准的STL,属于SGI STL的私有代码
技术和iterator_traits技术相同,只是定义的类型不同,作用场合不同
如POD就是__type_traits中定义的一种类型
部分代码如下:
struct __true_type { };
struct __false_type { };
template <class type>
struct __type_traits
{
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type; // 是否是POD类型
};
__STL_TEMPLATE_NULL struct __type_traits<char> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
__STL_TEMPLATE_NULL struct __type_traits<signed char>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned char>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
__STL_TEMPLATE_NULL struct __type_traits<short>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
// ... 每种基本类型都有定义
// 对原生的指针类型进行定义
template <class T>
struct __type_traits<T*>
{
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
STL源码剖析:迭代器的更多相关文章
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
1 STL迭代器原理 1.1 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...
- STL源码剖析--迭代器(转)
一.为什么需要traits编程技术 前面说了很多关于traits的光荣事迹,但是却一直没有介绍traits究竟是个什么东西,究竟是用来干什么的?traits在英文解释中就是特性,下面将会引入trait ...
- STL源码剖析(迭代器)
在STL中,容器跟算法是分开设计的,算法是通过迭代器来对容器进行操作的. 在算法运用迭代器的时候,可能会用到其相应的型别,例如返回值为容器中元素的型别,又或者说根据迭代器的类型来选择更好的算法等等. ...
- 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法
大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
- (原创滴~)STL源码剖析读书总结1——GP和内存管理
读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...
- STL源码剖析读书笔记之vector
STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...
- STL"源码"剖析
STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
随机推荐
- Redis高级特性介绍以及实例分析
Redis基础类型回顾 转自:http://www.jianshu.com/p/af7043e6c8f9 String Redis中最基本,也是最简单的数据类型.注意,VALUE既可以是简单的Stri ...
- C#/VB.NET 在PDF中添加文件包(Portfolio)
PDF文件包(Portfolio)允许用户将多种不同类型的文件如Word.Excel.PDF.PowerPoint和图片等集合到一个PDF文件中,用户可以打开.更改PDF文件包中的单个文件.添加文件包 ...
- 利用oracle数据库闪回功能将oracle数据库按时间点恢复
oracle更新脚本把原数据冲了,并且没有备份,急煞我也 解决办法: oracle数据库有闪回功能: select * from tab 可以查出已被删除的表 ...
- Nginx 反向代理可以缓存 HTTP POST 请求页面吗?
摘要: Nginx 反向代理可以缓存 HTTP POST 请求页面吗? 2017-09-05 景峯 Netkiller 本文节选自<Netkiller Web 手札> 作者:netkil ...
- oracle数据库插入日期格式字符串给date类型字段
首先执行 alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'; 然后执行insert语句而无需使用to_date函数
- 让对象拥有状态——C#中的状态模式
大家好,老胡又在博客和大家见面了,在聊今天的主角之前,老胡先给大家讲一个以前发生的故事. 真实的故事 当老胡还是小胡的时候,跟随团队一起开发一款游戏.这款游戏是一款末日生存类游戏,玩家可以 收集资 ...
- 十.总结drf视图
一.对一个资源的五个操作: 如users资源: 序列化是把模型/表中数据以json格式的数据返回给前端,反序列化是把前端通过http post提交过来的json格式数据(data)插入到数据库. 小 ...
- 服务认证(JWT)
上一篇已经讲了微服务组件中的 路由网关(Zuul),但是未介绍服务认证相关,本章主要讲解基于Spring Security 与 JJWT 实现 JWT(JSON Web Token)为接口做授权处理… ...
- Sharepoint 2013设置customErrors
原文地址:http://www.cnblogs.com/renzh/archive/2013/03/05/2944309.html#3407239 一.首先设置IIS中的Web.config文件 找到 ...
- 看球的巴士——线性dp
[题目描述] 两个球队的支持者要一起坐车去看球,他们已经排成了一列.我们要让他们分乘若干辆巴士,同一辆巴士上的人必须在队伍中是连续的.为了在车上不起冲突,希望两队的支持者人数尽量相等,差至多是D.有一 ...