以下内容主要是根据侯捷老师的教学视频所总结的:
最原始的写法
#inclide<cstddef>
#include<iostream>
using namespace std;
class First {
public:
First(int x):i(x){};
void* operator new(size_t);
void operator delete(void*, size_t);
private:
First* next;
static First* freeStore;
static const int Chunk;
int i;
};
First* First::freeStore=0;
const int First::Chunk=24;
void* First::operator new(size_t size)
{
First *p;
if (!freeStore)
{
size_t chunk=Chunk* size;
freeStore=p=reinterpret_cast<First*>(new char[chunk]);
for(;p!=&freeStore[Chunk-1];++p)
p->next=p+1;
p->next=0;
}
p=freeStore;
freeStore=freeStore->next;
return p;
}
void First::operator delete(void* p,size_t)
{
(static_cast<First*>(p))->next=freeStore;
freeStore=static_cast<First*>(p);
}
int main()
{
size_t const N = 100;
First* p[N];
for (int i = 0; i < N; ++i)
p[i] = new Screen(i);
for (int i = 0; i < 10; ++i)
cout << p[i] << endl;
for (int i = 0; i < N; ++i)
{
delete p[i];
}
return 0;
}
优化后的写法
上面有个问题就是,你一个对象必须要包含一个指针成员变量,第一、虽然省去了cookie, 但是也增加了内存使用量,接下就要利用一种技术就是嵌入式指针的方式,说起来很炫酷,其实就是一块内存复用。
struct person
{
int age;
string name;
};
class second {
private:
union
{person item;
person* next;}
public:
static void* operator new(size_t size);
static void operator delete(void* deadObject, size_t size);
private:
static const int BLOCK_SIZE;
static Second* headOfFreeList;
};
second* second::headOfFreeList;
const int second::BLOCK_SIZE = 512;
void* second::operator new(size_t size)
{
if (size != sizeof(second)) return ::operator new(size);
second* p = headOfFreeList;
if (p) headOfFreeList = p->next;
else {
second* newBlock = static_cast<second*>(::operator new(BLOCK_SIZE * sizeof(second)));
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;
}
void second::operator delete(void* deadObject, size_t size)
{
if (deadObject == 0) return;
if (size != sizeof(second)) {
::operator delete(deadObject);
return;
}
Airplane* carcass = static_cast<second*>(deadObject);
carcass->next = headOfFreeList;
headOfFreeList = carcass;
}
最后的版本
可以看到,通过内存复用,指针已经省了,但是耦合度比较高,下面继续改进
#include<iostream>
using namespace std;
struct obj{struct obj* next;};
class Allocator
{
public:
void* allocate(size_t);
void deallocate(void*, size_t);
private:
obj* freeStore = nullptr;
const int CHUNK = 5;
};
void* Allocator::allocate(size_t size)
{
obj* p;
if (!freeStore) {
size_t chunk = CHUNK * size;
freeStore = p = (obj*)malloc(chunk);
for (int i = 0; i < (CHUNK - 1); ++i) {
p->next = (obj*)((char*)p + size);
p = p->next;
}
p->next = nullptr;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void Allocator::deallocate(void* p, size_t size)
{
((obj*)p)->next = freeStore;
freeStore = (obj*)p;
}
class Foo {
public:
long L;
string str;
static Allocator myAlloc;
public:
Foo(long l) :L(l){}
static void* operator new(size_t size)
{
return myAlloc.allocate(size);
}
static void operator delete(void* pdead,size_t size)
{
return myAlloc.deallocate(pdead,size);
}
};
Allocator Foo::myAlloc;
int main()
{
Foo* p[100];
for (int i = 0; i < 23; ++i) {
p[i] = new Foo(i);
cout << p[i] << " " << p[i]->L << endl;
}
for (int i = 0; i < 23; ++i) {
delete p[i];
}
return 0;
}
|