自定义内存操做的意义:前端
- 下降 malloc 调用次数,提升内存空间利用率(每次 malloc 会携带上下 cookies[8bytes]标记)
- 下降 malloc 调用次数,提升内存管理速度
#include <cstddef> #include <iostream> using namespace std; class Screen { public: Screen(int x) : i(x) { } int get() { return i; } // 默认 static void *operator new(size_t); // 默认 static void operator delete(void*, size_t); private: Screen *next; // 这种设计会引起多耗用一个 next 的疑虑,下种实现更好 static Screen *freeStore; static const int screenChunk; private: int i; }; Screen *Screen::freeStore = 0; const int Screen::screenChunk = 24; void *Screen::operator new(size_t size) { Screen *p; if (!freeStore) { // 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; } // 并为将内存归还给系统,任由 Screen 接管(不算是内存泄露) void Screen::operator delete(void* p, size_t) { // 讲 deleted object 插回 free list 前端 (static_cast<Screen*>(p))->next = freeStore; freeStore = (static_cast<Screen*>(p)); } void func_1() { cout << "==== " << "Screen::operator new" << " ====" << endl; cout << sizeof(Screen) << endl; size_t const N = 100; Screen *p[N]; for (size_t i=0; i<N; ++i) p[i] = new Screen(i); for (size_t i=0; i<10; ++i) cout << p[i] << endl; for (size_t i=0; i<N; ++i) delete p[i]; } void func_2() { cout << "==== " << "::operator new" << " ====" << endl; cout << sizeof(Screen) << endl; size_t const N = 100; Screen *p[N]; for (size_t i=0; i<N; ++i) p[i] = ::new Screen(i); for (size_t i=0; i<10; ++i) cout << p[i] << endl; for (size_t i=0; i<N; ++i) :: delete p[i]; } int main() { func_1(); func_2(); return 0; }
输出:【如下输出证实自定义内存管理提升了空间利用率】ios
==== Screen::operator new ==== // 内存间隔 8 8 0x10080e8 0x10080f0 0x10080f8 0x1008100 0x1008108 0x1008110 0x1008118 0x1008120 0x1008128 0x1008130 ==== ::operator new ==== // 内存间隔 16, 包含 8 bytes cookies (上、下) 8 0x1001630 0x10084d0 0x10084e0 0x10084f0 0x1008500 0x1008510 0x1008520 0x1008530 0x1008540 0x1008550
#include <cstddef> #include <iostream> using namespace std; class Airplane { private: struct AirplaneRep { unsigned long miles; char type; }; private: union { AirplaneRep rep; // 此处针对使用中的 object Airplane *next; // 此处针对 free list 上的 object }; public: unsigned long getMiles() { 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); private: static const int BLOCK_SIZE; static Airplane *headOfFreeList; }; const int Airplane::BLOCK_SIZE = 512; Airplane *Airplane::headOfFreeList = nullptr; 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; ++i) newBlock[i].next = &newBlock[i+1]; newBlock[BLOCK_SIZE-1].next = 0; // 结束 list p = newBlock; headOfFreeList = &newBlock[1]; } return p; } // operator delete 接收一个内存块,若是大小正确,就把它加到 free list 前端 void Airplane::operator delete(void *deadObject, size_t size) { if (deadObject == 0) return; // 若是大小有误,转交给 ::operator delete [继承时发生] if (size != sizeof(Airplane)) { ::operator delete(deadObject); return; } Airplane *carcass = static_cast<Airplane*>(deadObject); carcass->next = headOfFreeList; headOfFreeList = carcass; } void func_1() { cout << "==== " << "Airplane::operator new" << " ====" << endl; size_t const N =100; Airplane *p[N]; for (size_t i=0; i<N; ++i) p[i] = new Airplane; // 随机测试 object 是否正常 p[1]->set(100, 'A'); p[5]->set(1000, 'B'); p[9]->set(10000, 'C'); // 输出前 10 个 pointer, 用以比较其间隔 for (size_t i=0; i<10; ++i) cout << p[i] << endl; for (size_t i=0; i<N; ++i) delete p[i]; } void func_2() { cout << "==== " << "::operator new" << " ====" << endl; size_t const N =100; Airplane *p[N]; for (size_t i=0; i<N; ++i) p[i] = ::new Airplane; // 随机测试 object 是否正常 p[1]->set(100, 'A'); p[5]->set(1000, 'B'); p[9]->set(10000, 'C'); // 输出前 10 个 pointer, 用以比较其间隔 for (size_t i=0; i<10; ++i) cout << p[i] << endl; for (size_t i=0; i<N; ++i) ::delete p[i]; } int main() { cout << sizeof(Airplane) << endl; // 注意输出,考虑字节对齐 !! func_1(); func_2(); return 0; }
输出:cookie
8 ==== Airplane::operator new ==== // 内存间隔 8 0xed80e8 0xed80f0 0xed80f8 0xed8100 0xed8108 0xed8110 0xed8118 0xed8120 0xed8128 0xed8130 ==== ::operator new ==== // 内存间隔 16, 包含 8 bytes cookies (上、下) 0xed1630 0xed90f0 0xed9100 0xed9110 0xed9120 0xed9130 0xed9140 0xed9150 0xed9160 0xed9170