天天看點

allocatorallocator

allocator

vs的 allocator 位置

#include <xmemory>
           

vs 中的實作:

大概vs認為如果是内部封裝的,都會在前面加下劃線。是以,在xmemory頭檔案有個define

#define _ALLOCATOR	allocator
           

然後,目前檔案的下面就有了

_ALLOCATOR

的類模闆.

這裡有兩個版本,一個是普通版本,一個是特化版本。

/*
template<class _Ty>
	class _ALLOCATOR : public _Allocator_base< _Ty>
    {
      //...
    };

template<> class _ALLOCATOR<void>
{
  //...
};
*/
           

稍微分析一下:

由于我不是太喜歡開頭加各種下劃線,是以我就自己修改下命名了。。

Allocator_base 類

template<class Ty>
	struct Allocator_base
	{	// base class for generic allocators
	typedef Ty value_type;
	};

// 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;
	};
           

注:

  • 我把 _Ty 寫成了 Ty
  • 我把 _Allocator_base 寫成了 Allocator_base

其實上面寫得很清楚,隻是定義了模闆 傳入參數的類型, 以後 咱們傳入的類型就在模闆裡面就是這個。

allocator

其實這個類并不是太難了解,不過我是一邊看類,一邊向上翻那幾個函數的,這裡有幾個需要記錄下:

  • _FARQ 這個宏
    • 後面注釋:specify standard memory model 翻譯就是指定标準記憶體模型
    • 由于後面是空的,大概應該是給編譯器,或者其他的使用,至少不是我
    • (這裡我是忽略的,因為我認為學習應該先分層?主要目的是想看看allocator)
  • _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);
      }
    */
    //替換後  這個就是擷取一段記憶體的函數
    template< typename Ty >
    Ty* Func_Allocate(size_t Count, Ty*)
    {
      void* ptr = nullptr;
      if (Count <= 0)   //其實這裡size_t 就是unsigned..但是我也不知道他為啥這樣寫,俺也不敢問...
      {   
        Count = 0;
      }
      else if(
                ((size_t)(-1) / sizeof(Ty) < Count)                       // 定義了邊界,-1轉換成unsigned 就是unsigned的最大值。最多擷取元素個數,還小于這個個數,就傳回bad allocat
                || (ptr = ::operator new(Count* sizeof(Ty)) == nullptr)   //這裡做了擷取記憶體的操作~如果沒new成功,就傳回 bad allocat
              )
      {
        throw bad_alloc(0);
      }  
    
      return ( (Ty*)ptr);
    }
    
               
  • _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));
    }
    
    template<class _Ty1> inline
    void _Construct(_Ty1 _FARQ *_Ptr)
    {	// construct object at _Ptr with default value
    void _FARQ *_Vptr = _Ptr;
    
    ::new (_Vptr) _Ty1();
    }
    */
    
    template<typename Ty1, typename Ty2>
    void Func_Construct(Ty1 Ptr, Ty2 Val)
    {
    	void* Vptr = Ptr;
    	::new(Vptr) Ty1(::std::forward<Ty2>(Val));		//這裡進行了初始化,Ptr指向的對象進行了初始化
    }
    
               
  • _Destroy 調用析構的函數
/* 源碼大概就長這樣,很好懂
	template<class _Ty> inline
	void _Destroy(_Ty _FARQ *_Ptr)
	{	// destroy object at _Ptr
	_Ptr->~_Ty();
	}
	*/
template<typename Ty> inline
void Func_Destroy(Ty* Ptr)
{
	Ptr->~Ty();
}

           
/* 同理 這裡是源碼
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;

	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)
		}

	template<class _Other>
		_ALLOCATOR(const _ALLOCATOR<_Other>&) _THROW0()
		{	// construct from a related allocator (do nothing)
		}

	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);
		}

	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);
		}
	};
*/

// 這裡是我替換後的版本
template < typename Ty >
class allocator : public Allocator_base< Ty >
{
public:
  typedef Allocator_base<Ty> Mybase;
  typedef typename Mybase::value_type value_type;     //這兩行,是拿到了父類定義的value_type

  typedef value_type* pointer;                        //定義了Ty的指針 在這裡叫 pointer
  typedef value_type& reference;                      //定義了Ty的引用 在這裡叫 reference
  typedef const value_type* const_pointer;            // const 指針
  typedef const value_type& const_reference;          // const 引用

  typedef size_t size_type;     
  typedef ptrdiff_t difference_type;

  template < typename Other >
  struct rebind
  {
    //将 allocator< Other > 定義為 other 類型
    typedef allocator< Other > other;
  };

  //---------- 這裡開始算是 alocator 的各種method -----
  //--begin: 這裡是擷取指針的函數
  pointer address(reference Val) const
	{	// return address of mutable Val
	   return ((pointer) &(char&)Val);     //這裡猜測使用char作為類型轉換的中介,大概是因為char是基本類型中最小的,誰都可以轉換,且都能讀取到東西
	}

  const_pointer address(const_reference Val) const
  {	// return address of nonmutable Val
    return ((const_pointer) &(char&)Val);
  }
  //--end

  //--begin: 構造函數,拷貝構造,指派操作符
  allocator() throw()
  {	// construct default allocator (do nothing)
  }

  allocator(const allocator<Ty>&) throw()
  {	// construct by copying (do nothing)
  }

  template<typename Other>
  allocator(const allocator<Other>&) throw()
  {	// construct from a related allocator (do nothing)
  }

  template<typename Other>
  allocator<Ty>& operator=(const allocator<Other>&)
  {	// assign from a related allocator (do nothing)
    return (*this);
  }
  //--end.

	//-- begin: 這裡是最重要的功能函數擷取記憶體,以及釋放記憶體
	void deallocate(pointer Ptr, size_type)
	{
		::operator delete(Ptr);
	}

	pointer allocate(size_type Count)
	{
		return (Func_Allocate(Count, (pointer)0));			//這裡調用之前的一個全局函數
	}

	pointer allocate(size_type Count, const void*)
	{
		return allocate(Count);											//這裡調用了上面的函數 allocate
	}
	//--end

	//-- begin: 這裡進行初始化和銷毀~
	void construct(pointer Ptr, const Ty& Val)
	{	// construct object at Ptr with value Val
	  Func_Construct(Ptr, Val);
	}

	void construct(pointer Ptr, Ty&& Val)
	{	// construct object at Ptr with value Val
		::new ((void*)Ptr) Ty(::std::forward<Ty>(Val));
	}

	template<class Other>
	void construct(pointer Ptr, Other&& Val)
	{	// construct object at Ptr with value Val
		::new ((void* )Ptr) Ty(::std::forward<Other>(Val));
	}

	void destroy(pointer Ptr)
	{	// destroy object at Ptr
			Destroy(Ptr);
	}
	//-- end


	//-- begin: 擷取能夠存儲的最大個數
	size_t max_size() const throw()
	{
		size_t Count = (size_t)(-1) / sizeof(Ty);
		return (0 < Count ? Count : 1);
	}
};


           

繼續閱讀