如何自定義一個內存池?

目錄

我們先寫個簡單的第一版內存分配器:

第二版

第三版Alloctor

第四版Alloctor


我們先寫個簡單的第一版內存分配器:

//推進式單向鏈表操作
	/*
	分配24*size個內存空間
	可以見圖PreAlloctor
	*/
	class FirstAlloctor
	{
	public:
		FirstAlloctor(std::size_t x) :i(x)
		{
		}
		~FirstAlloctor()
		{
		}
		std::size_t Get()
		{
			std::cout <<"PreAlloctor第一版在"<< __FILE__ << __LINE__ << std::endl;
			return i;
		}
		void ShowWhereIAm()
		{
			std::cout << "PreAlloctor第一版在" << __FILE__ << __LINE__ << std::endl;
		}
		void* operator new(std::size_t size)
		{
			FirstAlloctor* p;
			if (!freeStore)
			{
				std::size_t chunk = screenChunk * size;
				//
				freeStore = p = reinterpret_cast<FirstAlloctor*>(new char[chunk]);

				for (; p != &freeStore[screenChunk - 1]; ++p)
				{
					p->next = p + 1;
				}
				p->next = 0;
			}
			p = freeStore;
			freeStore = freeStore->next;
			return p;
		}
		void operator delete(void* del, std::size_t)
		{
			FirstAlloctor* p = static_cast<FirstAlloctor*>(del);
			p->next = freeStore;
			freeStore = p;
		}
		FirstAlloctor* next=nullptr;

	private:

		static FirstAlloctor* freeStore;
		static const int screenChunk;
		std::size_t i;
	};
	FirstAlloctor* FirstAlloctor::freeStore = 0;
	const int FirstAlloctor::screenChunk = 5;

第二版

//第二版PreAlloctor升級版
	class SecondAlloctor
	{
	private:
		//都是複製粘貼,windows下unsigned long佔4個字節,不管32還是64
		//Linux32佔4個,64位佔8個
		struct AirPlaneRep
		{
			unsigned long miles;
			char type;
		};
		union //匿名union,既可以存數據,也可以存下一個指針,省空間。
		{
			AirPlaneRep rep;
			SecondAlloctor* next;
		};
	public:
		unsigned long GetMiles()
		{
			return rep.miles;
		}
		char GetType()
		{
			
			return rep.type;
		}
		void ShowWhereIAm()
		{
			std::cout << "PreAlloctor第二版在" << __FILE__ << __LINE__ << std::endl;
		}
		void Set(unsigned long m, char t)
		{
			rep.miles = m;
			rep.type = t;
		}
		//截止到這裏就要考慮幾個問題:
		//1.多態問題。
		//2.省去1次串接操作
		//3.用union節省了一次內存
		static void* operator new(std::size_t size)
		{

			//檢查需要分配的大小,如果是子類的話直接分配最大的。
			if (size!=sizeof(SecondAlloctor))
			{
				return ::operator new(size);
			}
			SecondAlloctor* p = headOfFreeList;
			if (p)
			{
				headOfFreeList = p->next;
			}
			else
			{
				SecondAlloctor* newBlock = static_cast<SecondAlloctor*>(::operator new(BLOCK_SIZE * sizeof(SecondAlloctor)));
				//爲什麼從1開始呢?因爲從0開始沒意義,p第一次就要返回,也就是0位置第一次就要返回,
				//其實,headOfFreeList的起始位置在1,而不是0,所以p本身設不設置next都行,因爲內存管理器要求極致的效率,所以能省就省。
				for (int i=1;i<BLOCK_SIZE-1;++i)
				{
					newBlock[i].next = &newBlock[i + 1];
					
				}
				newBlock[BLOCK_SIZE - 1].next = 0;
				p = newBlock;
				headOfFreeList = &newBlock[1];

			}
			return p;

		}
		static void operator delete(void* deadObject,std::size_t size)
		{
			if (deadObject==0)
			{
				return;
			}
			if (size!=sizeof(SecondAlloctor))
			{
				::operator delete(deadObject);
				return;
			}
			SecondAlloctor* carass = static_cast<SecondAlloctor*>(deadObject);

			carass->next = headOfFreeList;
			headOfFreeList = carass;
		}
		static const int BLOCK_SIZE;

		static SecondAlloctor* headOfFreeList;

	private:

	};
	SecondAlloctor* SecondAlloctor::headOfFreeList;
	const int SecondAlloctor::BLOCK_SIZE = 512;

第三版Alloctor

//第三版,之前的不夠通用,所以就打算改了。

	class ThreeAlloctor
	{
	public:
		ThreeAlloctor();
		~ThreeAlloctor();
		void* Allocate(std::size_t size)
		{
			obj* p;
			if (!freeStore)
			{
				std::size_t chunk = CHUNK * size;
				p = static_cast<obj*>( malloc(chunk));
				freeStore = p;
				//原版認爲是0開始,但是本人認爲可以從0開始
				for (std::size_t i = 1; i < CHUNK; i++)
				{
					//p->next=
					p->next = (obj*)((char*)p + size);
					p = p->next;
				}
				p->next = nullptr;

			}
			p = freeStore;
			freeStore = freeStore->next;
			return p;
		}
		void DeAllocate(void* del,std::size_t size)
		{
			((obj*)del)->next = freeStore;
			freeStore = (obj*)del;
		}
	private:
		struct obj 
		{
			struct obj* next;
		};
		obj* freeStore = nullptr;
		const std::size_t CHUNK = 5;
	};

	ThreeAlloctor::ThreeAlloctor()
	{
	}

	ThreeAlloctor::~ThreeAlloctor()
	{
	}
	//第三版的使用者
	void ThreeVersion()
	{
		std::cout << "第三版在" << __FILE__ << __LINE__ << std::endl;
	}
	class ThreeAlloctor_User
	{
	public:
		ThreeAlloctor_User();
		~ThreeAlloctor_User();
		long L;
		std::string str;
	protected:
		static ThreeAlloctor myAllocate;
	public:
		void* operator new(size_t size)
		{
			myAllocate.Allocate(size);
		}
		void operator delete(void* del, size_t size)
		{
			myAllocate.DeAllocate(del, size);
		}
	private:

	};

	ThreeAlloctor_User::ThreeAlloctor_User():L(0),str("")
	{
	}

	ThreeAlloctor_User::~ThreeAlloctor_User()
	{
	}
	ThreeAlloctor ThreeAlloctor_User::myAllocate;

第四版Alloctor

主要也就是加入了宏定義,對使用者使用提供了方便,提升了代碼重用性。

#define DECLEAR_POOL_ALLOCATE()\
	protected:\
		static ThreeAlloctor myAllocate;\
	public:\
		void* operator new(size_t size)\
		{\
			myAllocate.Allocate(size);\
		}\
		void operator delete(void* del, size_t size)\
		{\
			myAllocate.DeAllocate(del, size);\
		}
#define IMPLEMENT_POOL_ALLOCATE(class_name)\
ThreeAlloctor class_name::myAllocate;


	//第四版爲了提高代碼重用性,改用宏定義
	//第四版的使用者
	void FourVersion()
	{
		std::cout << "第四版在" << __FILE__ << __LINE__ << std::endl;
	}
	class Foo1
	{
	public:
		Foo1() :L(0), str("")
		{}
		~Foo1()
		{}
		long L;
		std::string str;

		DECLEAR_POOL_ALLOCATE()

	private:

	};

	IMPLEMENT_POOL_ALLOCATE(Foo1)
	

 

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