C++STL的空間配置器將內存的分配、釋放,對象的構造、析構都分開執行,內存分配由alloc::allocate()負責,內存的釋放由alloc::deallocate()負責;對象的構造由::construct()負責,對象的析構由::destroy()負責。函數
下面爲源碼和註釋:指針
#include <new.h> //使用placement new //使用placement new在已經分配的內存上構造對象 template <class T1, class T2> inline void construct(T1* p, const T2& value) { new (p) T1(value); } //第一個版本,接受一個指針 //調用對象的析構函數,它須要有non-trivial destructor template <class T> inline void destroy(T* pointer) { pointer->~T(); } //第二個版本 //針對迭代器爲char*和wchar_t*的特化版本 inline void destroy(char*, char*) {} inline void destroy(wchar_t*, wchar_t*) {} //接受兩個迭代器,找出元素的類型 template <class ForwardIterator> inline void destroy(ForwardIterator first, ForwardIterator last) { __destroy(first, last, value_type(first)); } //判斷元素的類型是否有trivial destructor template <class ForwardIterator, class T> inline void __destroy(ForwardIterator first, ForwardIterator last, T*) { typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor; __destroy_aux(first, last, trivial_destructor()); } //元素的類型有non-trivial destructor template <class ForwardIterator> inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) { for ( ; first < last; ++first) destroy(&*first); } //元素的類型有trivial destructor template <class ForwardIterator> inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {}
在內存配置方面,STL分爲兩級配置器,當請求的內存大於128bytes的時候調用第一級配置器,當請求的內存小於等於128bytes的時候調用第二級配置器。如圖:code
第一級配置器源碼:對象
template <int inst> class __malloc_alloc_template { private: static void *oom_malloc(size_t); static void *oom_realloc(void *, size_t); #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG static void (* __malloc_alloc_oom_handler)(); #endif public: static void * allocate(size_t n) { void *result = malloc(n); if (0 == result) result = oom_malloc(n); return result; } static void deallocate(void *p, size_t /* n */) { free(p); } static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz) { void * result = realloc(p, new_sz); if (0 == result) result = oom_realloc(p, new_sz); return result; } static void (* set_malloc_handler(void (*f)()))() { void (* old)() = __malloc_alloc_oom_handler; __malloc_alloc_oom_handler = f; return(old); } }; // malloc_alloc out-of-memory handling #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG template <int inst> void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0; #endif template <int inst> void * __malloc_alloc_template<inst>::oom_malloc(size_t n) { void (* my_malloc_handler)(); void *result; for (;;) { my_malloc_handler = __malloc_alloc_oom_handler; if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; } (*my_malloc_handler)(); result = malloc(n); if (result) return(result); } } template <int inst> void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n) { void (* my_malloc_handler)(); void *result; for (;;) { my_malloc_handler = __malloc_alloc_oom_handler; if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; } (*my_malloc_handler)(); result = realloc(p, n); if (result) return(result); } }