深入理解 STL allocator

由于std::set,std::multiset,std::map,std::multimap四种容器的插入删除操作性能高并且自动排序,在很多时候比如需要动态操作时往往会使用它们,然后由于容器内部使用的是节点,每次的插入或删除都要调用new或delete,往往容易造成碎片和性能下降,于是自定义的allocator出现了。

这篇文章的目的就是详细讲解std::allocator的内部结构,为实现自定义的allocator奠基。

 

贴出STL源码,通过增加注释讲解

// xmemory internal header (from <memory>) #pragma once #ifndef _XMEMORY_ #define _XMEMORY_ #ifndef RC_INVOKED #include <cstdlib> #include <new> #include <xutility> // 说明:std::allocator将内存分配与释放、对象的构造与销毁独立出来, // 分别为内存分配、对象构造、对象销毁、内存释放。 #pragma pack(push,_CRT_PACKING) #pragma warning(push,3) #define _ALLOCATOR allocator // 由于下方使用了operator new函数,因此需要先取消new的宏定义 #pragma push_macro("new") #undef new #pragma warning(disable: 4100) #ifndef _FARQ /* specify standard memory model */ #define _FARQ #define _PDFT ptrdiff_t #define _SIZT size_t #endif /* _FARQ */ _STD_BEGIN // 这里是内存分配 // TEMPLATE FUNCTION _Allocate template<class _Ty> inline _Ty _FARQ *_Allocate(_SIZT _Count, _Ty _FARQ *) { // allocate storage for _Count elements of type _Ty void *_Ptr = 0; if (_Count <= 0) _Count = 0; else if (((_SIZT)(-1) / sizeof (_Ty) < _Count) || (_Ptr = ::operator new(_Count * sizeof (_Ty))) == 0) _THROW_NCEE(bad_alloc, 0); return ((_Ty _FARQ *)_Ptr); } // 使用 placement new 进行对象的拷贝构造放置 // TEMPLATE FUNCTION _Construct template<class _Ty1, class _Ty2> inline void _Construct(_Ty1 _FARQ *_Ptr, _Ty2&& _Val) { // construct object at _Ptr with value _Val void _FARQ *_Vptr = _Ptr; ::new (_Vptr) _Ty1(_STD forward<_Ty2>(_Val)); } // 使用 placement new 进行对象的默认构造放置 template<class _Ty1> inline void _Construct(_Ty1 _FARQ *_Ptr) { // construct object at _Ptr with default value void _FARQ *_Vptr = _Ptr; ::new (_Vptr) _Ty1(); } // 对象销毁(析构函数) // TEMPLATE FUNCTION _Destroy template<class _Ty> inline void _Destroy(_Ty _FARQ *_Ptr) { // destroy object at _Ptr _Ptr->~_Ty(); } // 内嵌字符串类型不用析构,特化版本供优化使用 template<> inline void _Destroy(char _FARQ *) { // destroy a char (do nothing) } template<> inline void _Destroy(wchar_t _FARQ *) { // destroy a wchar_t (do nothing) } #ifdef _NATIVE_WCHAR_T_DEFINED template<> inline void _Destroy(unsigned short _FARQ *) { // destroy a unsigned short (do nothing) } #endif /* _NATIVE_WCHAR_T_DEFINED */ // 根据指针类型选择是否为 POD 数据类型 // TEMPLATE FUNCTION _Destroy_range template<class _Alloc> inline void _Destroy_range(typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al) { // destroy [_First, _Last) _Destroy_range(_First, _Last, _Al, _Ptr_cat(_First, _Last)); } // 非 POD 数据类型需要显示调用析构函数 template<class _Alloc> inline void _Destroy_range(typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al, _Nonscalar_ptr_iterator_tag) { // destroy [_First, _Last), arbitrary type for (; _First != _Last; ++_First) _Dest_val(_Al, _First); } // POD 数据类型不需要调用析构函数 template<class _Alloc> inline void _Destroy_range(typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al, _Scalar_ptr_iterator_tag) { // destroy [_First, _Last), scalar type (do nothing) } // TEMPLATE FUNCTION addressof template<class _Ty> inline _Ty * addressof(_Ty& _Val) { // return address of _Val return ((_Ty *) &(char&)_Val); } // TEMPLATE CLASS _Allocator_base template<class _Ty> struct _Allocator_base { // base class for generic allocators typedef _Ty value_type; }; // 偏特化,去除 const 属性 // TEMPLATE CLASS _Allocator_base<const _Ty> template<class _Ty> struct _Allocator_base<const _Ty> { // base class for generic allocators for const _Ty typedef _Ty value_type; }; // TEMPLATE CLASS _ALLOCATOR template<class _Ty> class _ALLOCATOR : public _Allocator_base<_Ty> { // generic allocator for objects of class _Ty public: typedef _Allocator_base<_Ty> _Mybase; typedef typename _Mybase::value_type value_type; typedef value_type _FARQ *pointer; typedef value_type _FARQ& reference; typedef const value_type _FARQ *const_pointer; typedef const value_type _FARQ& const_reference; typedef _SIZT size_type; typedef _PDFT difference_type; // 由于在STL容器中allocator是以模板参数传入的,而对于节点型容器, // 如list, set, map,需要重新绑定数据结构,因而 rebind 便会用到 template<class _Other> struct rebind { // convert this type to _ALLOCATOR<_Other> typedef _ALLOCATOR<_Other> other; }; pointer address(reference _Val) const { // return address of mutable _Val return ((pointer) &(char&)_Val); } const_pointer address(const_reference _Val) const { // return address of nonmutable _Val return ((const_pointer) &(char&)_Val); } _ALLOCATOR() _THROW0() { // construct default allocator (do nothing) } _ALLOCATOR(const _ALLOCATOR<_Ty>&) _THROW0() { // construct by copying (do nothing) } // 这里使用了 Coercion by Member Template 惯用法 template<class _Other> _ALLOCATOR(const _ALLOCATOR<_Other>&) _THROW0() { // construct from a related allocator (do nothing) } // 这里使用了 Coercion by Member Template 惯用法 template<class _Other> _ALLOCATOR<_Ty>& operator=(const _ALLOCATOR<_Other>&) { // assign from a related allocator (do nothing) return (*this); } // 内存释放 void deallocate(pointer _Ptr, size_type) { // deallocate object at _Ptr, ignore size ::operator delete(_Ptr); } // 内存分配 pointer allocate(size_type _Count) { // allocate array of _Count elements return (_Allocate(_Count, (pointer)0)); } pointer allocate(size_type _Count, const void _FARQ *) { // allocate array of _Count elements, ignore hint return (allocate(_Count)); } void construct(pointer _Ptr, const _Ty& _Val) { // construct object at _Ptr with value _Val _Construct(_Ptr, _Val); } // placement new void construct(pointer _Ptr, _Ty&& _Val) { // construct object at _Ptr with value _Val ::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Ty>(_Val)); } template<class _Other> void construct(pointer _Ptr, _Other&& _Val) { // construct object at _Ptr with value _Val ::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Other>(_Val)); } // 对象销毁 void destroy(pointer _Ptr) { // destroy object at _Ptr _Destroy(_Ptr); } _SIZT max_size() const _THROW0() { // estimate maximum array size _SIZT _Count = (_SIZT)(-1) / sizeof (_Ty); return (0 < _Count ? _Count : 1); } }; // 特化版本,void 类型通常是无意义的 // CLASS _ALLOCATOR<void> template<> class _ALLOCATOR<void> { // generic _ALLOCATOR for type void public: typedef void _Ty; typedef _Ty _FARQ *pointer; typedef const _Ty _FARQ *const_pointer; typedef _Ty value_type; // rebind 必须重定义 template<class _Other> struct rebind { // convert this type to an _ALLOCATOR<_Other> typedef _ALLOCATOR<_Other> other; }; _ALLOCATOR() _THROW0() { // construct default allocator (do nothing) } _ALLOCATOR(const _ALLOCATOR<_Ty>&) _THROW0() { // construct by copying (do nothing) } template<class _Other> _ALLOCATOR(const _ALLOCATOR<_Other>&) _THROW0() { // construct from related allocator (do nothing) } template<class _Other> _ALLOCATOR<_Ty>& operator=(const _ALLOCATOR<_Other>&) { // assign from a related allocator (do nothing) return (*this); } }; // allocator内部由于没有数据,因而总是相同的功能 template<class _Ty, class _Other> inline bool operator==(const allocator<_Ty>&, const allocator<_Other>&) _THROW0() { // test for allocator equality return (true); } template<class _Ty, class _Other> inline bool operator!=(const allocator<_Ty>& _Left, const allocator<_Other>& _Right) _THROW0() { // test for allocator inequality return (!(_Left == _Right)); } // TEMPLATE FUNCTIONS _Cons_val AND _Dest_val template<class _Alloc, class _Ty1, class _Ty2> void _Cons_val(_Alloc& _Alval, _Ty1 *_Pdest, _Ty2&& _Src) { // construct using allocator _Alval.construct(_Pdest, _STD forward<_Ty2>(_Src)); } template<class _Alloc, class _Ty1> void _Dest_val(_Alloc& _Alval, _Ty1 *_Pdest) { // destroy using allocator _Alval.destroy(_Pdest); } _STD_END #pragma pop_macro("new") #pragma warning(pop) #pragma pack(pop) #endif /* RC_INVOKED */ #endif /* _XMEMORY_ */ /* * This file is derived from software bearing the following * restrictions: * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this * software and its documentation for any purpose is hereby * granted without fee, provided that the above copyright notice * appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation. * Hewlett-Packard Company makes no representations about the * suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. */ /* * Copyright (c) 1992-2009 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. V5.20:0009 */

 

附注:

(1)注意 rebind 结构的使用和作用

(2)Coercion by Member Template 惯用法的使用和作用

 

你可能感兴趣的:(object,function,iterator,Class,reference,permissions)