1.STL allocator

从vector的定义出发,追溯其内存申请方法。

1.vector 使用 allocator申请内存。

  1. 先看vector的定义。
template  //使用默认的_STL_DEFAULT_ALLOCATOR;
class vector : protected _Vector_base<_Tp, _Alloc> //protected继承自_Vector_base;
{
...
}
  1. Vector_base
template  
class _Vector_base {
public:
  typedef _Alloc allocator_type;
  allocator_type get_allocator() const { return allocator_type(); }

  _Vector_base(const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
  _Vector_base(size_t __n, const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) 
  {
    _M_start = _M_allocate(__n);
    _M_finish = _M_start;
    _M_end_of_storage = _M_start + __n;
  }

  ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }

protected:
  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;

  typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;//simple_alloc作为其allocator。
  _Tp* _M_allocate(size_t __n)
    { return _M_data_allocator::allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n) 
    { _M_data_allocator::deallocate(__p, __n); }
};
  1. 找到 STL_DEFAULT_ALLOCATOR的定义
# ifndef __STL_DEFAULT_ALLOCATOR
#   ifdef __STL_USE_STD_ALLOCATORS
#     define __STL_DEFAULT_ALLOCATOR(T) allocator< T >
#   else
#     define __STL_DEFAULT_ALLOCATOR(T) alloc //使用的是此定义。
#   endif
# endif
  1. 再找到alloc的定义
    stl_alloc.h
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc; 
typedef __default_alloc_template single_client_alloc;

default_alloc_template表示采用了2级配置器。

  1. simple_alloc
template
class simple_alloc {

public: 
    static _Tp* allocate(size_t __n)
      { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
    static _Tp* allocate(void)
      { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
    static void deallocate(_Tp* __p, size_t __n)
      { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
    static void deallocate(_Tp* __p)
      { _Alloc::deallocate(__p, sizeof (_Tp)); }
};

simple_alloc统一了allocator的接口。vector默认使用的allocator__default_alloc_template

2. __default_alloc_template

  1. 内存申请
template 
class __default_alloc_template {
...
public:

  /* __n must be > 0      */
  static void* allocate(size_t __n)
  {
    void* __ret = 0;

    if (__n > (size_t) _MAX_BYTES) {
      __ret = malloc_alloc::allocate(__n);
    }
    else {
      _Obj* __STL_VOLATILE* __my_free_list
          = _S_free_list + _S_freelist_index(__n);
      // Acquire the lock here with a constructor call.
      // This ensures that it is released in exit or during stack
      // unwinding.
#     ifndef _NOTHREADS
      /*REFERENCED*/
      _Lock __lock_instance;
#     endif
      _Obj* __RESTRICT __result = *__my_free_list;
      if (__result == 0)
        __ret = _S_refill(_S_round_up(__n));
      else {
        *__my_free_list = __result -> _M_free_list_link;
        __ret = __result;
      }
    }

    return __ret;
  };

} ;

简单来说申请内存超过 _MAX_BYTES就从一个内存链表中获取内存,其中_MAX_BYTES=128,反之就使用1级内存配置器。1及内存配置器大概等于直接使用malloc&free函数。

总结

STL存在两级内存配置器,大于128字节的内存申请使用一级配置器。小于128字节的内存申请使用2级配置器。
1级配置器使用malloc在堆中申请空间,并能够处理内存申请失败。2级迭代器通过维护内存区块链表处理小块内存的申请,其内存来源于内存池。内存池内存不够的时候会使用1级配置器申请内存,增加内存池。

你可能感兴趣的:(1.STL allocator)