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提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
随机推荐
- Lucene5多条件查询
lucene是一个很强大的搜索工具,最近公司项目上用到,结合JAVA1234所讲,对多条件查询做出总结 先描述一下我的多条件需求,如果和您的类似,继续往下看. 1.我的Lucene搜索会在很多地方使用 ...
- Centos安装redis详解
redis官方网站对redis的安装已有介绍,但没有redis环境的安装,redis自动启动服务安装等等: redis官网:https://redis.io 本文以centos6为基础安装redis ...
- [ C++ ] set_new_handler解析
当 operator new 中malloc返回值为0(NULL)时,表示分配内存失败(可能是因为内存不足), 此时会通过_callnewh()调用用户通过set_new_handler()设定的ne ...
- 调用php命令出错
调用php -v命令.php artisan route:list等命令均出现一下错误. MIB search path: c:/usr/share/snmp/mibsCannot find modu ...
- 面试官:你精通多少种语言的 Hello World?
Hello World,是程序员入门编程语言的第一课.不论是C.C++还是Java ,我们写的第一个程序就是它了,还记得小编在大一C语言课上,花了一整节课时间才把它打印到控制台上.万事开头难啊,相信看 ...
- 并发06--JAVA中的并发工具类
1.等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作. 使用join也可以完成这个操作,代码示例如下: package com.exam ...
- 小师妹学JVM之:JIT中的PrintAssembly
目录 简介 使用PrintAssembly 输出过滤 总结 简介 想不想了解JVM最最底层的运行机制?想不想从本质上理解java代码的执行过程?想不想对你的代码进行进一步的优化和性能提升? 如果你的回 ...
- 46道Linux面试题送给你(后续会不断更新)
绝对路径用什么符号表示? 当前目录.上层目录用什么表示?主目录用什么表示? 切换目录用什么命令? 答案: # 绝对路径: 如/etc/init.d # 当前目录和上层目录: ./ ../ # 主目录: ...
- 客官,来看看AspNetCore的身份验证吧
开篇 这段时间潜水了太久,终于有时间可以更新一篇文章了. 通过本篇文章您将Get: Http的一些身份验证概念 在AspNetCore中实现身份验证方案 JWT等概念的基础知识 使用Bearer To ...
- SpringBoot项目部署到tomcat
SpringBoot部署到tomcat 一.修改maven.xml 1.添加<.packaging>war</.packaging>,打包为war包 <packaging ...