赫莲娜包包是山寨吗:stl_alloc.h

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 05:53:25

sgi stl的allocate由2级配置器组成, 默认为第二级, 第二级配置器分配内存的时候, 首先查看需要分配的内存块大小,如果大于160, 调用第一级配置器, 否则用内存池来分配内存。 这样对小块内存的分配效率高,不容易产生内存碎片。
一级配置器:
template
class __malloc_alloc_template {
二级配置器
template
class __default_alloc_template {

sgi stl有自己的配置器实现, 缺省的时候不使用标准配置器。
以vector为例:
vector的定义:
template
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, 这个时候是标准配置器, 我们可以用自定义的allocator, 否则__STL_USE_STD_ALLOCATORS为alloc, alloc是sgi stl的一个配置器实现,这个时候即使我们传入自己的配置器, 也会被忽略.

最后还有一个template
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 _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 _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 _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
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