STL源码剖析

  花了两天时间略读了一下《stl源码分析》,看了个大体,对于细节并没有深究。之所以想翻翻这本书,主要是想看看stl中的特性、适配器的具体实现。看完之后收获还是蛮大的,模板的各种组合让我眼前一亮,下面大概总结一些内容。

  1.内存分配:sgi内存分配采用两级实现,对于大内存块的申请(大于128k)由第一级实现,第一级实现较简单,直接调用malloc和free。对于小于128k的内存请求,由第二级实现。第二级使用了内存池,维护了一些链表,分别指向不同大小的空闲内存块,这些内存块都是8的倍数的大小,分别是8k,16k,24k,...,128k。分配内存时,根据请求大小找到相应链表的表头,然后从表头摘取一个结点块,回收的时候也是从表头插入。第二级内存分配的实现方式跟linux操作系统的空闲内存管理很相似,不过内存回收的时候有区别,linux内存管理还涉及到空闲块的合并。

  2.迭代器:要设计一种迭代器,必须对容器的具体实现有丰富的了解,所以把迭代器的实现交给容器的设计者,这样就可以是容器的实现细节得以封装,所以每一种STL容器都提供了专属的迭代器。迭代器中的end()具体指向了哪个位置?对于vector这种由连续内存块来实现的容器,end()指向数组之后的一个位置。而对于list,map,set这种由”结点“实现的容器,会有专门的一个结点,该结点含有一些重要的信息,比如指向开头结点的指针。为什么有些迭代器只能是向前的?因为其容器的内部实现决定了它的迭代器只能是前向的,比如单向链表的迭代器当然只能是向前的了。

  3.容器:deque的结构挺复杂的,使用了分段数组,并使用了一个map数组来映射不同分段数组的地址,通过封装,使其使用起来就像是个连续的数组一样。stack和queue的内部结构使用的是deque。vector容器增长的平均时间复杂度是O(1)。具体计算,大家可以自己想想。

  4.traits:c++的特性让我见识了c++抽象的强大,通过增加一层抽象,使问题的解决变得很微妙。这部分主要利用了模板的类型推断能力。通过偏特化,能够粹取出类类型和原始指针的特性。印象很深的一个例子是advance函数。

template<class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag){
    whie(n--) ++i;
}

template<class ForwardIterator, class Distance>
inline void __advance(ForwardIterato& i, Distance n, fowrd_iterator_tag){
    __advance(i,n,input_iterator_tag());
}

template<class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag){
    if(n >= 0){
        while(n--) ++i;
    }else{
        while(n++) --i;
    }
}

template<class RandomAccessIterator, class Distance >
linue void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag){
    i += n;
}

  实现了四个不同的函数重载,再增加一个上层函数advance(),粹取出迭代器的类型,并调用相应的__advance版本。

template<class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n){
        __advance(i,n,iterator_traits<InputIterator>::iterator_category());
}

  5.适配器:适配器的实现主要是在内部包含了一个对象,在外面展示不同的接口,内部实际上还是间接使用了其所包含的对象。为什么说为了让一个函数对象在stl是可适配的?因为在外层类中要使用到内部包含类型的某些”特性“,比如bind1st,就要使用到内部二元函数仿函数的first_argument_type。所以为了能够被适配,一般都要继承unary_function和binary_function。

  6.采用辅助函数:我们知道使用模板类声明一个对象,需要给出具体的类型,有时手动地给出具体类型会很麻烦,那么有没有办法让编译器自动推导出具体的类型呢?这里使用了”增加一层抽象“,使用模板函数,模板函数具有自动推导的功能,利用模板函数推导出来的类型来具现模板类。比如下面的例子。

template<class Operation>
class binder1st : public unary_function<typename Operation::second_argument_type, typename Operation::result_type>{
protected:
    Operation op;
    typename Operation::first_argument_type value;
public:
    binder1st(const Operation& x, const typename Operation::first_argument_type& y):op(x),value(y){}

    typename Operation::result_type
    operator()(const typename Operation::second_argument_type& x)const{
        return op(value,x);
    }
};

template<class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x){
    typedef typename Operation::first_argument_type arg1_type;
    return binder1st<Operation>(op,arg1_type(x));
}

  嗯,就先总结到这些吧。其他的一些东西要么之前了解得比较熟了,那么印象不是很深刻,就不写出来了。

时间: 2024-08-08 10:50:31

STL源码剖析的相关文章

《STL源码剖析》---stl_pair.h阅读笔记

pair是STL中的模板类型,它可以存储两个元素,它也被称作"对组".在map中已经用到了它,pair其实就是一个struct结构,存有两个public的元素,重载了几个运算符,没有什么成员函数,源代码很简单. G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_pair.h 完整列表 /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy,

《STL源码剖析》---stl_tree.h阅读笔记

STL中,关联式容器的内部结构是一颗平衡二叉树,以便获得良好的搜索效率.红黑树是平衡二叉树的一种,它不像AVL树那样要求绝对平衡,降低了对旋转的要求,但是其性能并没有下降很多,它的搜索.插入.删除都能以O(nlogn)时间完成.平衡可以在一次或者两次旋转解决,是"性价比"很高的平衡二叉树. RB-tree(red black tree)红黑树是平衡二叉树.它满足一下规则 (1)每个节点不是红色就是黑色. (2)根节点是黑色. (3)如果节点为红色,则其子节点比为黑色. (4)任何一个节

《STL源码剖析》---stl_iterator.h阅读笔记

STL设计的中心思想是将容器(container)和算法(algorithm)分开,迭代器是容器(container)和算法(algorithm)之间的桥梁. 迭代器可以如下定义:提供一种方法,能够依序寻访某个容器内的所有元素,而又无需暴露该容器的内部表达方式. 在阅读代码之前,要先了解一个新概念:Traits编程技法 template <class T> struct MyIter { typedef T value_type //内嵌型别声明 T *ptr; MyIter(T *p = 0

STL 源码剖析 算法 stl_algo.h -- search_n

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie search_n ---------------------------------------------------------------------------------------- 描述:在序列[first, last) 所涵盖的区间中,查找"连续 count 个符合条件之元素"所形成的子序列, 并返回迭代器 last 思路: 1.首先找出 value 第一次出现点

STL 源码剖析 算法 stl_algo.h -- lower_bound

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie lower_bound(应用于有序区间) -------------------------------------------------------------------------------------------------------------------------- 描述:二分查找,返回一个迭代器指向每一个"不小于 value "的元素, 或 value 应该

STL 源码剖析 算法 stl_algo.h -- upper_bound

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie upper_bound(应用于有序区间) ------------------------------------------------------------------------------------------------------------------------------------------------- 描述:受STL区间前闭后开习惯的影响,upper_boun

STL 源码剖析 算法 stl_algo.h -- binary_search

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie binary_search ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 描

STL 源码剖析 算法 stl_algo.h -- next_permutation

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie next_permutation ----------------------------------------------------------------------- 描述: 取得 [first, last) 所标示之序列的下一个排列组合.如果没有,返回 false,有,返回true 思路: 从后往前 1.找两个相邻元素,令左端的元素为*i,右端的元素为*ii,且满足 *i <

STL源码剖析 — 空间配置器(allocator)

前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配置器,配置的对象,是内存.(以下内容来自<STL源码剖析>) 空间配置器的标准接口 根据STL的规范,allocator的必要接口 各种typedef 1 allocator::value_type 2 allocator::pointer 3 allocator::const_pointer 4

STL&quot;源码&quot;剖析-重点知识总结

STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合套用: 容器(Containers):各种数据结构,如:vector.list.deque.set.map.用来存放数据.从实现的角度来看,STL容器是一种class template. 算法(algorithms):各种常用算法,如:sort.search.copy.erase.从实现的角度来看,STL算法