c++實現一個簡單的空間配置器allocator

c++實現一個簡單的空間配置器allocator


      c++中內存分配和對象構造是分開來的,內存的分配類似malloc函數在內存空間開闢一段空間,但是裏面不保存任何數據。對象的構造相當於給這段空間複製。


      這麼做的理由有兩點:

  •       在預先分配的內存中構造對象很浪費,可能創建從不使用的對象,當實際使用預先分配的對象時,被使用的對象往往又必須重新賦以新值。
  •       如果預分配的內存必須被構造,某些類就不能使用它。(?不理解)


      C++中內存分配一般有三個層次:

  1. 使用new創建對象, delete刪除對象
  2. 使用allocator分配未初始化的內存,使用construct和destroy構造和析構對象
  3. 使用operator new分配內存,operator delete刪除內存,placement new創建對象,顯式調用析構函數析構對象


第一層:

      當使用new表達式時,實際發生三個步驟。首先,該表達式調用名爲operator new的標準函數庫,分配足夠大的原始的未初始化的內存,以保存指定類型的一個對象;接下來,運行該類型的一個構造函數,用指定初始化式構造對象;最後,返回指向新分配並構造的對象的指針。

      當使用delete的時候類似,先適當的析構,然後釋放內存 .

void main()
{
	int *p=new int(10);
	printf("%d",*p);
}


第二層

      使用allocator類,它提供各種類型的內存分配和對象的構造與撤銷,allocator類講內存分配和對象構造分開。當allocator對象分配內存時,它分配適當大小並排列成保存給定類型對象的空間。但是,它分配的內存時未構造的,allocator的用戶必須分別使用construct和destory放置在改內存中的對象。

#include<iostream>
#include<memory>			//使用allocator必須包含memory
using namespace std;

void main()
{
	allocator<int> alloc;
	int *ptr=alloc.allocate(1);
	alloc.construct(ptr,10);
	printf("%d\n",*ptr);
}

結果:

10
請按任意鍵繼續. . .


第三層

      使用標準庫函數operator new和operator delete,使用它們可以獲得未構造的內存,下面的*p=10相當於構造函數.

#include<iostream>
using namespace std;

void main()
{
	int *p=static_cast<int*>(operator new[](sizeof(int)));
	*p=10;
}

      使用placement new表示式來構造對象,指在已分配的原始內存中初始化一個對象,它不分配內存,只構造對象,它可以使用任何構造函數,並直接建立對象,相對於allocator中的construct就比較靈活,construct只能使用複製構造函數,這樣在進制使用複製構造函數的地方allocator是不能用的。

placement new的形式爲:

new (placae-address) type;

new(placae-address) type (initializer-list)


#include<iostream>
using namespace std;

void main()
{
	int *p=static_cast<int*>(operator new[](sizeof(int)));
	new (p) int(10);
}

再舉個類的例子

#include<iostream>
using namespace std;

class A
{
public:
	int data;
};

void main()
{
	A *ptr=static_cast<A*>(operator new[](sizeof(A)*2));
	new (ptr) A;
	printf("%d",(*ptr).data);
}


有了上面的例子,我們就可以設計一個我們自定義的簡單的空間配置器

#include<iostream>
using namespace std;

//分配內存
template<typename T>
inline T* _allocate(unsigned int size,T*)
{
	T* tmp=static_cast<T*>(operator new[](size*sizeof(T)));
	if(tmp==0)
	{
		cout<<"'out of memory"<<endl;
		exit(1);
	}
	return tmp;
}

//釋放內存
template<typename T>
inline void _deallocate(T* buffer)
{
	operator delete(buffer);
}

//構造對象
template<typename T1,typename T2>
inline void _construct(T1 *p,const T2 &value)
{
	new (p) T1(value);
}

//析構對象
template<typename T>
inline void _destory(T *ptr)
{
	ptr->~T();
}

//我的空間配置器
template<typename T>
class myAllocator
{
public:
	typedef T value_type;
	typedef T* pointer;
	typedef const T* const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef unsigned int size_type;

	template<typename U>
	struct rebind
	{
		typedef allocator<U> other;
	};

	pointer allocate(size_type n,const void *hint=0)
	{
		return _allocate(n,(pointer)0);
	}

	void deallocate(pointer p,size_type n)
	{
		_deallocate(p);
	}

	void construct(pointer p,const T &value)
	{
		_construct(p,value);
	}

	void destroy(pointer p)
	{
		_destory(p);
	}
};

//主函數,檢查正確性
void main()
{
	myAllocator<int> alloc;
	int *ptr=alloc.allocate(2);
	alloc.construct(ptr,10);
	printf("%d",*ptr);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章