在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源码剖析(迭代器)的更多相关文章

  1. STL源码剖析 迭代器(iterator)概念与编程技法(三)

    1 STL迭代器原理 1.1  迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...

  2. STL源码剖析--迭代器(转)

    一.为什么需要traits编程技术 前面说了很多关于traits的光荣事迹,但是却一直没有介绍traits究竟是个什么东西,究竟是用来干什么的?traits在英文解释中就是特性,下面将会引入trait ...

  3. 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

    大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...

  4. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  5. 【转载】STL"源码"剖析-重点知识总结

    原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...

  6. (原创滴~)STL源码剖析读书总结1——GP和内存管理

    读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...

  7. STL源码剖析读书笔记之vector

    STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...

  8. STL"源码"剖析

    STL"源码"剖析-重点知识总结   STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...

  9. 《STL源码剖析》相关面试题总结

    原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...

随机推荐

  1. 在CentOS6或RHEL6恢复上ext4文件系统误删除的文件

    首先说明: [root@CentOS6 ~]# rm -rf / //这条命令不可以执行 [root@CentOS6 ~]# rm -rf /* //这条命令可以执行,别去试 ext4文件系统上误删除 ...

  2. 在spring中手动编写事务

    利用事务模板TransactionTemplate来手动添加事务 public void addRant(Rant rant) { transactionTemplate.execute(-?tran ...

  3. BZOJ 1305 [CQOI2009]dance跳舞(二分+网络流)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1305 [题目大意] 一次舞会有n个男孩和n个女孩. 每首曲子开始时,所有男孩和女孩恰好 ...

  4. [BZOJ2216]Lightning Conductor

    原来决策单调性指的是这个东西... 一些DP可以写成$f_i=\max\limits_{j\lt i}g(i,j)$,设$p_i(p_i<j)$表示使得$g(i,j)$最大的$j$,如果$p_1 ...

  5. 【凸包】【三分】Gym - 101309D - Dome of Circus

    容易发现,圆锥体积和点的具体x.y坐标无关,只与其到z轴的距离sqrt(x*x+y*y)有关. 于是将这些三维的点都投射到二维的xOy平面的第二象限(sqrt(x*x+y*y),z),求个上凸壳,然后 ...

  6. 【二分】Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market

    傻逼二分 #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; ll ...

  7. Educational Codeforces Round 6 D. Professor GukiZ and Two Arrays 二分

    D. Professor GukiZ and Two Arrays 题目连接: http://www.codeforces.com/contest/620/problem/D Description ...

  8. What happens when a SQL Query runs?

    Posted by Padma Chitturi in Uncategorized. Leave a Comment Hi Folks, It has been such a long time th ...

  9. VC知识库

    VC知识库http://www.vckbase.com/index.php/code

  10. C# 中的.pdb/ .vshost.exe/ .vshost.exe.manifest文件

    转自 C# 中的.pdb/ .vshost.exe/ .vshost.exe.manifest文件讨论 pdb文件: 英文全称:Program Database File 中文全称:程序数据库 文件 ...