STL源码剖析——空间配置器

一.六大组件
  • 容器(Containers):各种数据结构,如Vector,List,Deque,Set,Map,用来存放数据
  • 算法(Algorithms):各种常用算法如Sort,Search,Copy,Erase,从实现的角度来看,STL算法是一种Function Templates
  • 迭代器(Iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化,从实现的角度来看,迭代器是一种将:Operators*,Operator->,Operator++,Operator–等相关操作予以重载的Class Template。
  • 仿函数(Functors): 行为类似函数,可作为算法的某种策略,常配合具体算法使用。
  • 配接器(适配器):一种用来修饰容器或仿函数或迭代器接口的东西,例如queue和stack。
  • 分配器(Allocators):负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的Class Template。
二.六大组件的关系

容器使用分配器分配数据存储的空间,算法通过迭代器存取容器内的内容,仿函数可以协助算法实现不同的策略,配接器可以修饰或者套接仿函数

三.allocator
  1. 实现一个简单的配置器(不符合规范),常常只需要定义一个allocator的模板类,然后在底层调用operator new()函数与operator delete()函数即可。
  2. new和delete关键字的操作过程
    new 先调用底层的operator new()分配空间,然后调用construct全局函数构造对象;delete 先调用destroy函数析构对象,然后调用 operator delete()释放空间。
    alloc注意:destroy一般来说有两个版本,当析构一个对象时直接调用对象析构函数即可,若是多个对象则先判断析构函数是否是一些无关痛痒的析构函数(即所谓的trivial destructor),若是的话就弃之不顾了,否则就需要一个个的调用对应的析构函数了,这大大提高了效率。
  3. 空间配置器的分级
    当用户申请的空间大于等于128个字节时,使用一级空间配置器。当用户申请的空间小于128个字节时,使用二级空间配置器。一级空间配置器的底层实现malloc,二级空间配置器的底层实现是内存池,其通过维护16个自由链表,负责16种小型区块的次配置。
    alloc
  4. 《STL源码剖析》中关于set_new_handler的理解
  5. 二级配置器自由列表原理
    list本来也没什么好说的,只是它这个自由链表的使用方式实在是骚,使用union结构,有效减少了内存消耗,既可以被我们使用obj.free_list_link作为一个指向块大小皆为8的倍数的链表,同时该变量又是真正的物理内存该链表的起始位置,是真的妙啊。。。
    至于16个自由链表管理的块大小如下表所示:
free_list12345678910111213141516
size(bytes)81624324048566472808896104112120128
  1. 简单说一说分配流程
  • 对于allocate当大于128bytes时在一级配置器里面分配内存,具体就是调用malloc,而当小于时就在这个free_list中查找合适的块,如果没有的话就向上取整到8的倍数的边界,返回合适的区块即可。最后调用refill为free_list重新填充区块。
  • 对于deallocate就比较简单了,大于128bytes使用一级配置器,底层调用free释放。对于小于128bytes的则直接找到对应的free_list接在后面即可。
四.内存池的设计实现

其实本质就是在自由链表的下层又搞了一层缓存,当自由链表没有了对应的块,甚至更大的块也找不到的时候就去内存池里面找,若是内存池里面也找不到对应的块,那么就调用malloc看还有没有物理内存可以使用,有的话就申请过来些,放置一半在内存池,另外的交给自由链表,自由链表交一个给客户,并将剩余的东西自己维护起来。最后若是物理内存里面也找不到物理块了就抛出bad_alloc异常。

五.内存基本处理工具

其实就是需要我们掌握以下5个对于学习STL源码异常重要的全局函数:

  • construct()
  • destory()
  • uninitialized_copy() 对应STL高层函数copy()
  • uninitialized_fill() 对应STL高层函数fill()
  • uninitialized_fill_n() 对应STL高层函数fill_n()
    按照STL书所讲的东西来看,基本后三个函数与他们对应封装的高级算法表现出一样的作用,所以此处,直接学习三个STL的高级算法吧,以下代码皆来自cplusplus.com网站:
1.copy()函数
template<class InputIterator, class OutputIterator>
  OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
  while (first!=last) {
    *result = *first;
    ++result; ++first;
  }
  return result;
}

具体示例:

// copy algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::copy
#include <vector>       // std::vector
int main () {
  int myints[]={10,20,30,40,50,60,70};
  std::vector<int> myvector (7);

  std::copy ( myints, myints+7, myvector.begin() );

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it = myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;

  std::cout << '\n';

  return 0; //输出:myvector contains: 10 20 30 40 50 60 70
}
2.fill()函数
template <class ForwardIterator, class T>
  void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
  while (first != last) {
    *first = val;
    ++first;
  }
}

示例如下:

// fill algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::fill
#include <vector>       // std::vector

int main () {
  std::vector<int> myvector (8);                       // myvector: 0 0 0 0 0 0 0 0

  std::fill (myvector.begin(),myvector.begin()+4,5);   // myvector: 5 5 5 5 0 0 0 0
  std::fill (myvector.begin()+3,myvector.end()-2,8);   // myvector: 5 5 5 8 8 8 0 0

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
//输出:myvector contains: 5 5 5 8 8 8 0 0
  return 0;
}
3.fill_n()函数
template <class OutputIterator, class Size, class T>
  OutputIterator fill_n (OutputIterator first, Size n, const T& val)
{
  while (n>0) {
    *first = val;
    ++first; --n;
  }
  return first;     // since C++11
}

示例如下:

// fill_n example
#include <iostream>     // std::cout
#include <algorithm>    // std::fill_n
#include <vector>       // std::vector

int main () {
  std::vector<int> myvector (8,10);        // myvector: 10 10 10 10 10 10 10 10

  std::fill_n (myvector.begin(),4,20);     // myvector: 20 20 20 20 10 10 10 10
  std::fill_n (myvector.begin()+3,3,33);   // myvector: 20 20 20 33 33 33 10 10

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
//输出:myvector contains: 20 20 20 33 33 33 10 10
  return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值