内存管理的目的:提高速度,降低空间浪费率
- 减少malloc的使用。(可以先分配一大块,再一点一点的使用)
- 较少cookie的使用。
版本一
#include <iostream>
using namespace std;
class Screen {
public:
Screen(int x):i(x) {}
int get() { return i; }
void* operator new(size_t);
void operator delete(void*, size_t);
private:
Screen* next; // 为了去掉cookie
static Screen* freeStore;
static const int screenChunk;
private:
int i;
};
Screen* Screen::freeStore = 0;
const int Screen::screenChunk = 24; // 创建24份,内存池
void* Screen::operator new(size_t size) {
Screen* p;
if (!freeStore) {
std::cout << "operator new" << std::endl;
//linked list是空的,所有申请一大块
size_t chunk = screenChunk * size;
freeStore = p = reinterpret_cast<Screen*> (new char[chunk]);
//将一大块分割成片,当做linked list串接起来
for (; p!=&freeStore[screenChunk-1]; ++p) {
p->next = p + 1;
}
p->next = 0;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void Screen::operator delete(void* p, size_t) {
//将deleted object 插入free list前端
(static_cast<Screen*>(p))->next = freeStore;
freeStore = static_cast<Screen*>(p);
}
int main() {
cout << sizeof(int) << endl;
cout << sizeof(Screen) << endl;
size_t const N = 100;
Screen* p[N];
for (int i = 0; i < N; ++i) {
p[i] = new Screen(i);
}
//输出前10个指针,比较其间隔,确认其没有cookie
for (int i = 0; i < 10; ++i) {
cout << p[i] << endl;
}
for (int i = 0; i < N; ++i) {
delete p[i];
}
return 0;
}
版本二
引入了union的使用
#include <iostream>
using namespace std;
class Airplane {
private:
struct AirplaneRep {
unsigned long miles;
char type;
};
private:
union {
AirplaneRep rep; //此指针对使用中的objects
Airplane* next; //此指针对free list 上的object
};
public:
unsigned long getMiles() { return rep.miles; }
char getType() { return rep.type; }
void set(unsigned long m, char t) { rep.miles = m; rep.type = t; }
public:
static void* operator new(size_t size);
static void operator delete(void* deadObject, size_t size);
public:
static const int BLOCK_SIZE;
static Airplane* headOfFreeList;
};
Airplane* Airplane::headOfFreeList;
const int Airplane::BLOCK_SIZE = 512;
void* Airplane::operator new(size_t size) {
//如果大小有误,转交给::operator new() (当继承发生的时候,大小会不同)
if (size != sizeof(Airplane)) {
return ::operator new(size);
}
Airplane*p = headOfFreeList;
if (p) {
//如果p有效,就把list头部下移一个
headOfFreeList = p->next;
}
else {
// free list已空,申请(分配一大块)
Airplane* newBlock = static_cast<Airplane*>(::operator new(BLOCK_SIZE* sizeof(Airplane)));
//将小块串成一个free list,但是跳过#0,因为它被当成本次成果
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 Airplane::operator delete(void* deadObject, size_t size) {
if (deadObject == 0) {
return;
}
if (size != sizeof(Airplane)) {
::operator delete(deadObject);
return;
}
Airplane* carcass = static_cast<Airplane*> (deadObject);
carcass->next = headOfFreeList;
headOfFreeList = carcass;
}
int main(int argc, char *argv[]) {
cout << sizeof(Airplane) << endl;
size_t const N = 100;
Airplane* p[N];
for(int i = 0; i < N; ++i) {
p[i] = new Airplane;
}
p[1] ->set(1000, 'A');
p[5] ->set(2000, 'B');
p[6] ->set(50000, 'C');
for (int i = 0; i < 10; ++i) {
cout << p[i] << endl;
}
for (int i = 0; i < N; ++i) {
delete p[i];
}
return 0;
}
两个版本都存在遗憾,申请的内存,不能及时还给系统,被自己存储起来。
static allocator(版本三)
上面的两个版本,需要在每个class中重复写member operator new 和 member operator delete。所有避免麻烦,将这个重复的操作包装起来:
#include <iostream>
using namespace std;
class Allocator {
private:
struct obj {
struct obj* next; // embedded pointer
};
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) {
//linked list为空,于是申请一大块
size_t chunk = CHUNK*size;
freeStore = p = (obj*)malloc(chunk);
//将分配得来的一大块当做linked list,小块小块串起来
for (int i = 0; i < (CHUNK-1); ++i) {
p->next = (obj*)((char*)p + size);
p = p->next;
}
p->next = nullptr; //last
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void Allocator::deallocate(void* p, size_t) {
//将*p收回插入free list前端
((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(int argc, char *argv[]) {
Foo foo(10);
return 0;
}
macro(宏) for static allcoator(版本四)
将版本三Foo等类中重复的东西,用宏代替: