<memory>中的allocator作爲STL中默認的內存分配器,它的定義如下:
template<typename _Tp>
class allocator: public __allocator_base<_Tp>{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;
typedef _Tp value_type;
template<typename _Tp1>
struct rebind{ typedef allocator<_Tp1> other; };
allocator() throw() { }
allocator(const allocator& __a) throw()
: __allocator_base<_Tp>(__a) { }
template<typename _Tp1>
allocator(const allocator<_Tp1>&) throw() { }
~allocator() throw() { }
};
template<>
class allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template<typename _Tp1>
struct rebind
{ typedef allocator<_Tp1> other; };
};
就是一些typedef和對void進行了特化。它的構造函數和析構函數都不拋出異常。rebind先不涉及。真正幹活的是父類__allocator_base。那__allocator_base又是何方神聖呢?
namespace std
{
template<typename _Tp>
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
}
__gnu_cxx是命名空間,__allocator_base是__gnu_cxx命名空間中new_allocator<_Tp>的別名。而在__gnu_cxx命名空間中,我們見到了new_allocator:
template<typename _Tp>
class new_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;
typedef _Tp value_type;
template<typename _Tp1>
struct rebind
{ typedef new_allocator<_Tp1> other; };
new_allocator() noexcept { }
new_allocator(const new_allocator&)noexcept { }
template<typename _Tp1>
new_allocator(const new_allocator<_Tp1>&) noexcept{ }
~new_allocator() noexcept { }
pointer
allocate(size_type __n, const void* = 0)
{
if (__n > this->max_size())
std::__throw_bad_alloc();
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
}
void
deallocate(pointer __p, size_type)
{ ::operator delete(__p); }
size_type
max_size() const _GLIBCXX_USE_NOEXCEPT
{ return size_t(-1) / sizeof(_Tp); }
void
construct(pointer __p, const _Tp& __val)
{ ::new((void *)__p) _Tp(__val); }
void
destroy(pointer __p) { __p->~_Tp(); }
};
我們看見了熟悉的allocate,deallocate,construct和destroy。
allocate使用::operator new申請內存,deallocate使用::operator delete釋放內存,construct使用placement new在指定的內存上構造對象,destroy析構對象。