sgi stl的allocate由2级配置器组成, 默认为第二级, 第二级配置器分配内存的时候, 首先查看需要分配的内存块大小,如果大于160, 调用第一级配置器, 否则用内存池来分配内存。 这样对小块内存的分配效率高,不容易产生内存碎片。 一级配置器: template <int __inst> class __malloc_alloc_template { 二级配置器 template <bool threads, int inst> class __default_alloc_template {
sgi stl有自己的配置器实现, 缺省的时候不使用标准配置器。 以vector为例: vector的定义: template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) > class vector : protected _Vector_base<_Tp, _Alloc> 这里__STL_DEFAULT_ALLOCATOR是这样的一个东西: 见stl_config.h # 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 如果定义了__STL_USE_STD_ALLOCATORS, 那么__STL_DEFAULT_ALLOCATOR 为 allocator<T>, 这个时候是标准配置器, 我们可以用自定义的allocator, 否则__STL_USE_STD_ALLOCATORS为alloc, alloc是sgi stl的一个配置器实现,这个时候即使我们传入自己的配置器, 也会被忽略.
最后还有一个template<class _Tp, class _Allocator> struct _Alloc_traits {} 并且根据不同的配置器作了特化。只有在定义了__STL_USE_STD_ALLOCATORS的时候, 才会定义这个类。 在各个容器中,使用_Alloc_traits来萃取当前使用的allocator的实际类型。 如vector: _Vector_base用来分配和释放内存, 并且封装了标准配置器和sgi配置器的不同。 当没有定义__STL_USE_STD_ALLOCATORS, 则使用的是alloc, 不需要_Alloc_traits. 此时就是确定使用alloc来分配, 不需要萃取类型信息。 _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; _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_USE_STD_ALLOCATORS template <class _Tp, class _Allocator, bool _IsStatic> class _Vector_alloc_base { public: typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type allocator_type; allocator_type get_allocator() const { return _M_data_allocator; }
_Vector_alloc_base(const allocator_type& __a) : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) {} protected: allocator_type _M_data_allocator; _Tp* _M_start; _Tp* _M_finish; _Tp* _M_end_of_storage;
_Tp* _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); } void _M_deallocate(_Tp* __p, size_t __n) { if (__p) _M_data_allocator.deallocate(__p, __n); } };
// Specialization for allocators that have the property that we don't // actually have to store an allocator object. template <class _Tp, class _Allocator> class _Vector_alloc_base<_Tp, _Allocator, true> { public: typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type allocator_type; allocator_type get_allocator() const { return allocator_type(); }
_Vector_alloc_base(const allocator_type&) : _M_start(0), _M_finish(0), _M_end_of_storage(0) {} protected: _Tp* _M_start; _Tp* _M_finish; _Tp* _M_end_of_storage;
typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; _Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); } void _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);} };
template <class _Tp, class _Alloc> struct _Vector_base : public _Vector_alloc_base<_Tp, _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless> { typedef _Vector_alloc_base<_Tp, _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless> _Base; typedef typename _Base::allocator_type allocator_type;
_Vector_base(const allocator_type& __a) : _Base(__a) {} _Vector_base(size_t __n, const allocator_type& __a) : _Base(__a) { _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); } };
_Vector_base从_Vector_alloc_base<_Tp, _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless>派生。 如果传入vector的模办参数_Alloc的类型为allocate<_Tp1>, 这是stl_alloc.h里定义的一个配置器, 封装了alloc, 实际分配删除都调用alloc进行。 根据_Alloc_traits的特化, _S_instanceless为true, 而如果_Alloc为自定义配置器,_S_instanceless为false. 当_S_instanceless为true, 则会使用_Alloc_traits<_Tp, _Allocator>::_Alloc_type作为真正的配置器。typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; _S_instanceless为false, 则使用_Alloc_traits<_Tp, _Allocator>::allocator_type。 这两个类型在_Alloc_traits中都有定义, 最后,根据配置器的特点, vector用萃取出的合适的配置器分配内存。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dummyedu/archive/2007/01/08/1477249.aspx
|