从vector的定义出发,追溯其内存申请方法。
1.vector 使用 allocator申请内存。
- 先看vector的定义。
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) > //使用默认的_STL_DEFAULT_ALLOCATOR;
class vector : protected _Vector_base<_Tp, _Alloc> //protected继承自_Vector_base;
{
...
}
- Vector_base
template <class _Tp, class _Alloc>
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); }
};
- 找到
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
- 再找到
alloc
的定义
stl_alloc.h
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
typedef __default_alloc_template<false, 0> single_client_alloc;
default_alloc_template
表示采用了2级配置器。
- simple_alloc
template<class _Tp, class _Alloc>
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
- 内存申请
template <bool threads, int inst>
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级配置器申请内存,增加内存池。