目錄
我們先寫個簡單的第一版內存分配器:
//推進式單向鏈表操作
/*
分配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)