示例1:在类中提前分配一块连续的内存池,减少cookie(分配内存时产生的头尾共8个字节,用于记录分配了多少内存)对内存的消耗
class Screen { public: Screen(int x) : i(x) {} int getData() { return i; } void* operator new(size_t); void operator delete(void*, size_t); private: static Screen* freeStore;//对象的内存地址 static const int screenChunk;//要获取的Screen类的个数,内存数量 = sizeof(Screen) * screenChunk Screen* next; int i; }; Screen* Screen::freeStore = nullptr; const int Screen::screenChunk = 4; void* Screen::operator new(size_t size){ Screen* p; //freeStore不为空表示预先拿到的内存还有位置 if (!freeStore) { size_t chunk = size * screenChunk; freeStore = p = reinterpret_cast<Screen*>(new char[chunk]); 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 size) { static_cast<Screen*>(p)->next = freeStore; freeStore = static_cast<Screen*>(p); } void test() { cout << "sizeof Screen: " << sizeof(Screen) << endl;//获取Screen大小 Screen* p[100]; for (int i = 0; i < 100; i++) { p[i] = new Screen(i); //创建 } for (int i = 0; i < 100; i++) { cout << "address: " << p[i] << " i = " << p[i]->getData() << endl; } for (int i = 0; i < 100; i++) { delete p[i]; //销毁 } }
结果:screenChunk取值为4,所以每4个Screen对象的空间是连续的
示例2:例1的优化版,加入embedded pointer
class Airplane { private: struct AirplaneRep { unsigned long miles; char type; }; union { AirplaneRep rep; Airplane* next; }; 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; } void* operator new(size_t size); void operator delete(void*, size_t); private: static Airplane* headOfFreeList; static const int BLOCK_SIZE; }; Airplane* Airplane::headOfFreeList = nullptr; const int Airplane::BLOCK_SIZE = 512; void* Airplane::operator new(size_t size){ if (size != sizeof(Airplane)) { return ::operator new(size); } Airplane* p = headOfFreeList; if (p) headOfFreeList = p->next; else { size_t total_size = size * BLOCK_SIZE; Airplane* newBLOCK = reinterpret_cast<Airplane*>(new char[total_size]); 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; } void test() { const int size = 100000; cout << "sizeof Airplane: " << sizeof(Airplane) << endl;//获取Screen大小 Airplane* p[size]; for (int i = 0; i < size; i++) { p[i] = new Airplane(); p[i]->set(i, i % 3); } for (int i = 0; i < size; i++) { cout << "address: " << p[i] << " i = " << p[i]->getMiles() << endl; } for (int i = 0; i < size; i++) { delete p[i];//销毁 } }
示例3:采用一个类来进行内存池,让所有类都能共用
示例4:加入宏定义