STL源码剖析读书笔记2

来源:互联网 发布:1688端口是干嘛的 编辑:程序博客网 时间:2024/05/22 13:11

空间适配器allocator

为什么不说allocator是内存适配器而是空间适配器,原因就是你可以写
allocat直接向硬盘取空间。

allocator标准接口

这里写图片描述
这里写图片描述
这里写图片描述

设计一个简单的空间配置器JJ::allocator

_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是以模板参数传入的,而对于节点型容器,    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);          }      };  

[1] placement new是重载operator new的一个标准、全局的版本,它不能被自定义的版本代替(不像普通的operator new和operator delete能够被替换成用户自定义的版本)。

它的原型如下:
void *operator new( size_t, void *p ) throw() { return p; }

使用方法如下:

  1. 缓冲区提前分配

可以使用堆的空间,也可以使用栈的空间,所以分配方式有如下两种:

class MyClass {…};
char *buf=new char[N*sizeof(MyClass)+ sizeof(int) ] ;
或者char buf[N*sizeof(MyClass)+ sizeof(int) ];

  1. 对象的构造

MyClass * pClass=new(buf) MyClass;

  1. 对象的销毁

一旦这个对象使用完毕,你必须显式的调用类的析构函数进行销毁对象。但此时内存空间不会被释放,以便其他的对象的构造。

pClass->~MyClass();

  1. 内存的释放

如果缓冲区在堆中,那么调用delete[] buf;进行内存的释放;如果在栈中,那么在其作用域内有效,跳出作用域,内存自动释放.

[2] size_t size=sizeof(i);//用sizeof操作得到变量i的类型的大小
ptrdiff_t diff=p2-p1;//指针的减法可以计算两个指针之间相隔的元素个数

[3]exit用在main内的时候无论main是否定义成void返回的值都是有效的,并且exit不需要考虑类型,exit⑴等价于return ⑴

原创粉丝点击