自定义内存操作的意义:
- 升高 malloc 调用次数,进步内存空间利用率(每次 malloc 会携带高低 cookies[8bytes]标记)
- 升高 malloc 调用次数,进步内存治理速度
实现一 [ref. C++ Primer 3/e,p.765]
#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;}
输入:【以下输入证实自定义内存治理进步了空间利用率】
==== Screen::operator new ==== // 内存距离 8 80x10080e80x10080f00x10080f80x10081000x10081080x10081100x10081180x10081200x10081280x1008130==== ::operator new ==== // 内存距离 16, 蕴含 8 bytes cookies (上、下)80x10016300x10084d00x10084e00x10084f00x10085000x10085100x10085200x10085300x10085400x1008550
实现二 [ref.Effective C++ 2e,item10]
#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;}
输入:
8==== Airplane::operator new ==== // 内存距离 80xed80e80xed80f00xed80f80xed81000xed81080xed81100xed81180xed81200xed81280xed8130==== ::operator new ==== // 内存距离 16, 蕴含 8 bytes cookies (上、下)0xed16300xed90f00xed91000xed91100xed91200xed91300xed91400xed91500xed91600xed9170