STL源码剖析:Allocator

STL源码剖析:Allocator

SGI标准的空间适配器

SGI标准的适配器名为 std::allocator。该空间适配器只是对c++的::operator new 和 ::operator delete做了一层浅封装,并且由于封装的缘故反而降低了效率。

template <class T>
inline T* allocate(ptrdiff_t size, T*) {
  set_new_handler(0);
  T* tmp = (T*)(::operator new (size_t)(size * sizeof(T)));
	if (tmp == 0) {
    cerr << "out of memory" << endl;
    exit(1);
  }
  return tmp;
}

template <class T>
inline void deallocate(T* buffer) {
  ::operator delete(buffer);
}

SGI特殊的空间适配器

SGI特殊的空间适配器称为 std::alloc

在该适配器中,将new和delete的操作细分为四个操作

  • 内存配置由alloc::allocate()负责
  • 内存释放由alloc::deallocate()负责
  • 对象的构造操作由::construct()负责
  • 对象的析构操作由::destroy()负责

构造和析构的基本工具:construct()和destroy()

构造函数construct()通过placement new 在已经分配的内存上调用对象的构造函数

template <class T1, class T2>
inline void construct(T1* p, const T2& value) {
  new (p) T1(value); 
}

析构函数有两个版本,第一个版本较简单,第二个版本较复杂

//第一个版本:
template <class T>
inline void destroy(T* pointer) {
  //调用该对象的析构函数
  pointer->~T();
}
//第二个版本
//析构first到last中的对象
template <class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last) {
  __destroy(first, last, value_type(first));
}

//判断元素的value type中是否有trivial destructor(不重要的析构函数)
template <class ForwardIterator, class T>
inline void __destroy(ForwardIterator first, ForwardIterator last, T*) {
  typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
  __destroy_aux(first, last, trivial_destructor());
}

//如果元素的数值型别有non_trivial destructor
template <class ForwardIterator>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) {
  for ( ; fitst < last; ++first) {
    destroy(&*first);
  }
}

//如果元素的数值型别有trivial destructor
template <class ForwardIterator>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __true_type) {}

//以下是destroy()第二版本针对迭代器char* 和 wchar_t*的特化版
inline void destroy(char*, char*) {}
inline void destroy(wchar_t*, wchar_t*) {}

一级配置器和二级配置器

二级配置器名为__default_alloc_template,其中

  • 维护16个自由链表,负责16种小型区块的次配置能力。
  • 内存池以malloc配置而得,如果内存不足,转调用一级配置器(一级配置器有处理程序)
  • 如果需求区块的大小大于128字节,就转调用第一级配置器

一级配置器名为__malloc_alloc_template,其中

  • allocate()直接使用malloc()
  • deallocate()直接使用free()
  • 模拟c++的set_new_handler()以处理内存不足的状况

空间配置函数allocate()

//n must be > 0
static void* allocate(size_t n) {
	obj * volatile * my_free_list;
  obj* result;
  //大于128字节就调用第一级配置器
  if (n > (size_t) __MAX_BYTES) {
    return(malloc_alloc::allocate(n));
  }
  //寻找16个free lists中适当的一个
  my_free_list = free_list + FREELIST_INDEX(n);
  result = *my_free_list;
  if (result == 0) {
    //如果没找到可用的node,则重新装填free list
    void *r = refill(ROUND_UP(n));
 		return r;
  }
  //调整free list
  *my_free_list = result->free_list_link;
  return (result);
}

空间释放函数deallocate()

//p不能为0
static void deallocate(void* p, size_t n) {
  obj* q = (obj *)p;
  obj* volatile* my_free_list;
  
  //大于128就调用第一级配置器
  if (n > (size_t)__MAX_BYTES) {
    malloc_alloc::deallocate(p, n);
    return;
  }
  //寻找对应的free list
  my_free_list = free_list + FREELIST_INDEX(n);
  //调整free list,回收区块
  q->free_list_link = *my_free_list;
  *my_free_list = q;
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值