STL源码剖析(迭代器)
在STL中,容器跟算法是分开设计的,算法是通过迭代器来对容器进行操作的。
在算法运用迭代器的时候,可能会用到其相应的型别,例如返回值为容器中元素的型别,又或者说根据迭代器的类型来选择更好的算法等等。
为了实现这一点,还有为了兼容内置型别的迭代器(vector迭代器直接使用原生pointer),STL使用了traits技法,用于提取迭代器的特性(相应的型别)。
1.首先在iterator中typedef相应的型别
// 这是迭代器的基类 所有迭代器必须定义这5种型别
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;
};
2.定义萃取器iter_traits
// 以迭代器为模板参数,用于萃取相应的型别
template <class Iterator>
struct iter_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
3.定义相应的偏特化版本(这就是为什么要使用iter_traits封装多一层),因为内置型别的迭代器并不是class,不能定义相应的型别。
// 原生指针的偏特化版
template <class T>
struct iter_traits<T*> {
typedef typename random_access_iter_tag iterator_category;
typedef typename T value_type;
typedef typename ptrdiff_t difference_type;
typedef typename T* pointer;
typedef typename T& reference;
}; // 原生const的偏特化版
template <class T>
struct iter_traits<const T*> {
typedef typename random_access_iter_tag iterator_category;
typedef typename T value_type;
typedef typename ptrdiff_t difference_type;
typedef typename const T* pointer;
typedef typename const T& reference;
};
4.5种迭代器类型,只是一个标志,用于根据萃取出来的iterator_category来选择相应的算法。
struct input_iter_tag {};
struct output_iter_tag {};
struct forward_iter_tag : public input_iter_tag {};
struct bidirectional_iter_tag : public forward_iter_tag {};
struct random_access_iter_tag : public bidirectional_iter_tag {};
下面是distance()的实现,展示了怎么使用traits萃取相应的型别。
// input迭代器只支持operator++
template<class InputIterator>
inline typename iter_traits<InputIterator>::difference_type
__distance(InputIterator first, InputIterator last, input_iter_tag)
{
iter_traits<InputIterator>::difference_type n = ;
while (first != last)
{
first++;
n++;
}
return n;
} // random access迭代器支持迭代器之间的加减法
template<class RandomAccessIterator>
inline typename iter_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iter_tag)
{
return last - first;
} // 根据迭代器的iterator_category来调用适合的版本
template<class Iterator>
inline typename iter_traits<Iterator>::difference_type
distance(Iterator first, Iterator last)
{
return __distance(first, last, iter_traits<Iterator>::iterator_category());
}
STL的__type_traits也是使用traits技法,它可以萃取一个class是否有不重要的构造函数、是否为POD类型等等。
// __type_traits也是运用traits技术
struct __true_type {};
struct __false_type {}; template <class type>
struct __type_traits {
// 默认为false 可以实现自己的偏特化版本
// 内置类型的偏特化版本定义在stl_config.h中 都是__true_type
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;
};
自定义的类型可以定义相应的偏特化版本,例如定义is_POD_type为__true_type,STL会在元素析构的时候只进行内存回收,而不调用析构函数以用来提高效率。
内存基本处理工具
STL定义了五个全局函数,作用于未初始化空间上,同样的它们也是使用了traits技法。
1.construct()跟destroy(),它们定义在stl_construct.h中
2.uninitialized_copy()、uninitialized_fill()、uninitialized_fill_n(),它们定义在stl_uninitialized中
STL源码剖析(迭代器)的更多相关文章
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
1 STL迭代器原理 1.1 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...
- STL源码剖析--迭代器(转)
一.为什么需要traits编程技术 前面说了很多关于traits的光荣事迹,但是却一直没有介绍traits究竟是个什么东西,究竟是用来干什么的?traits在英文解释中就是特性,下面将会引入trait ...
- 【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提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
随机推荐
- Requirejs快速使用
Requirejs是一个简单,实用,强大的前端模块化js库,它遵循AMD这一客户端模块定义规范,使用它能够使我们前端代码更加清晰高效加载,摆脱了以前前端代码杂乱无序的状态. 使用步骤如下: 1.下载r ...
- [NOI2015]小园丁与老司机(DP+上下界最小流)
由于每行点的个数不超过1000,所以行内DP可以使用$O(n^2)$算法. 先找到每个点所能直接到达的所有点(x,y,x+y或x-y相同),用排序实现. 第一问:以行为阶段,对于每行,暴力枚举最有路径 ...
- 【BFS】Tester Program
[poj1024]Tester Program Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2760 Accepted ...
- python基础之闭包函数与装饰器
闭包函数: 什么是闭包函数: 闭指的是定义在一个函数内部 包指的是该函数包含对外部作用域(非全局作用域)名字的引用 def counter(): n=0 def incr(): nonlocal n ...
- Unity3D 粒子系统
我们先来看看Particle System在Inspector视窗中的属性: 1.Transform:可以控制粒子在世界或者本地坐标的改变.但是有点注意的是,如果你改变Scale属性值是不会影响粒子的 ...
- [Git] 给git命令起别名
转载自:http://blog.csdn.net/qinjienj/article/details/7479886 程序员都是"懒惰"的,哪怕是执行一个命令的时候少敲了一个字母也感 ...
- [转]SSIS: By coding
本文转自:http://www.codeproject.com/Articles/604197/SSIS-By-coding Introduction SSIS better known as “SQ ...
- gmock学习01---Linux配置gmock
本文目的 本文主要介绍gmock 1.6.0版本在Linux上如何部署和使用. gmock是做什么的? 使用C++手动编写mock对象将会是一件十分耗时,易于出错,枯燥乏味的事情.gmock提供一整套 ...
- Delphi XE8 TStyleBook的使用
Delphi XE8来了,FMX的性能有了巨大的提升,比如:XE7下ListBox上下滑动的卡顿已经不复存在,直接用xe8编译后,再上下划动ListBox,已经变的非常流畅.另外,也见到有网友说,通过 ...
- AWR报告简易分析
Snap Id Snap Time Sessions Cursors/Session Begin Snap: 35669 2012-11-8 13:00 1246 11.3 End Snap: 356 ...