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提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
随机推荐
- Grunt Gulp Browserify Webpack
Grunt 是相比后面几个更早的项目,他依赖于各种插件的配置.这是一个很好的解决方案,但是请相信我,你不会想看到一个 300 行的 Gruntfile Gulp 提供了一个不一样的解决方案,而不是依赖 ...
- Java 生产者消费者 & 例题
Queue http://m635674608.iteye.com/blog/1739860 http://www.iteye.com/problems/84758 http://blog.csdn. ...
- 【UOJ #34】多项式乘法
http://uoj.ac/problem/34 看了好长时间的FFT和NTT啊qwq在原根那块磨蹭了好久_(:з」∠)_ 首先设答案多项式的长度拓展到2的幂次后为n,我们只要求出一个g(不是原根)满 ...
- 14年安徽省赛数论题etc.
关于最大公约数的疑惑 题目描述 小光是个十分喜欢素数的人,有一天他在学习最大公约数的时候突然想到了一个问题,他想知道从1到n这n个整数中有多少对最大公约数为素数的(x,y),即有多少(x,y),gcd ...
- 监视scrollview是否滚动到底
//监视scrollview是否滚动到底 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ [refreshHeaderViewegoRe ...
- Java异步编程——深入源码分析FutureTask
Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...
- NNVM代码阅读
op.h #define DMLC_ATTRIBUTE_UNUSED __attribute__((unused)) __attribute__((unused)):通常,如果声明了某个变量,但从未对 ...
- Scala访问修饰符
Scala 访问修饰符基本和Java的一样,分别有:private,protected,public. 如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public. Scala ...
- nodejs第一个练习:用Node.js建HTTP服务器
这是官方的一个例子, 在F盘建立一个tinyphp.js文件,内容: var http = require('http'); http.createServer(function (req, res) ...
- oracle 察看用户是否被锁,解锁以及改密码
以管理员身份登陆 察看用户状态(是否被锁) select * from dba_users where username='user1' 解锁 ALTER USER user1 ACCOUNT UN ...