重载类的 new,delete,new[],delete[] 运算符成员函数
1. 调用 new 时,先分配内存,后调用构造函数。调用构造函数的行为由编译器控制。2. 调用 delete 时,先调用析构函数,后释放内存。调用析构函数的行为由编译器控制。重载这四个运算符函数的目的是为了控制内存的分配与释放。如果需要对某个类型频繁地创建和销毁大量的对象, 这四个运算过程可能会耗费太多的时间,并且会产生内存碎片。这四个运算符函数的原型: void* operator new(size_t) throw(bad_alloc); void operator delete(void* pmem); void* operator new[](size_t sz) throw(bad_alloc); void operator delete[](void* pmem);重载时必须与原型一致!请看示例代码:#include#include #include #include #include #include using std::cout;using std::endl;using std::cerr;using std::bad_alloc;using std::hex;//void out_of_memory(){// cerr << "memory exhausted!\n";// exit(-1);//}template inline void DelObject(T *&pobj){ delete pobj; pobj = 0; // Don't forget to assigne pobj as 0.}template inline void DelObjArray(T *&parr) { delete []parr; parr = 0; // Don't forget to assigne parr as 0.}class NewDelType { union { unsigned char ch[4]; int val; }ts;public: enum { psize = 10 }; static unsigned char pool[]; static bool alloc_map[];public: NewDelType() { ts.val = 0x12345678; printf("%s, this=%p, ts=(%#x,%#x,%#x,%#x,%#x)\n", __func__,this,ts.val,ts.ch[0],ts.ch[1],ts.ch[2],ts.ch[3]); } ~NewDelType() { printf("%s, this=%p, ts=(%#x,%#x,%#x,%#x,%#x)\n", __func__,this,ts.val,ts.ch[0],ts.ch[1],ts.ch[2],ts.ch[3]); } void* operator new(size_t) throw(bad_alloc); void operator delete(void* pmem); void* operator new[](size_t sz) throw(bad_alloc); void operator delete[](void* pmem);};unsigned char NewDelType::pool[psize * sizeof(NewDelType)];bool NewDelType::alloc_map[psize] = {false};void* NewDelType::operator new(size_t) throw(bad_alloc) { for(int i = 0; i < psize; i++){ if(!alloc_map[i]) { printf("%s, to use block %d\n", __func__, i); alloc_map[i] = true; // Mark it used return pool + (i * sizeof(NewDelType)); } } printf("%s, to throw bad_alloc\n", __func__); throw bad_alloc();}void NewDelType::operator delete(void* pmem) { // Check for null pointer if(!pmem){ printf("%s, null pointer\n", __func__); return; } // Assume it was created in the pool // Calculate which block number it is: unsigned long block = (unsigned long)pmem - (unsigned long)pool; block /= sizeof(NewDelType); printf("%s, freeing block:(%p, %lu)\n", __func__, pmem, block); assert(block >= 0 && block < psize && alloc_map[block] == true); // Mark it free: alloc_map[block] = false;}void* NewDelType::operator new[](size_t sz) throw(bad_alloc) { assert( (sz - 8) % sizeof(NewDelType) == 0); int request = (sz - 8) / sizeof(NewDelType); assert(request >= 0 && request <= psize); printf("%s, sz = %lu, reqest = %d\n", __func__, sz, request); int avail = 0; int start = -1, end = -1; for(int i = 0; i < psize; ++i){ if(alloc_map[i] == false) ++avail; else avail = 0; if(avail == request){ end = i; start = end + 1 - request; break; } } if(avail == request){ for(int j = start; j <= end; ++j){ alloc_map[j] = true; } unsigned char *pbyte = pool + start * sizeof(NewDelType); printf("%s, to use block:(%p, %d, %d)\n", __func__, pbyte, start, end); printf("\t"); for(int k = 0; k < 12; ++k){ printf("0x%x ", pbyte[k]); } printf("\n"); return pbyte; } else{ printf("%s, to throw bad_alloc, avail = %d\n", __func__, avail); throw bad_alloc(); }}void NewDelType::operator delete[](void* pmem) { // Check for null pointer if(!pmem){ printf("%s, null pointer\n", __func__); return; } //The quantity of objects allocated was saved in the first byte. //WARNING: Maybe the quantity is not saved here for every case. unsigned char to_free = *(unsigned char *)pmem; printf("%s, pmem:(%p, %d)\n", __func__, pmem, to_free); printf("\t"); unsigned char *pbyte = (unsigned char *)pmem; for(int k = 0; k < 12; ++k){ printf("0x%x ", pbyte[k]); } printf("\n"); unsigned long block = (unsigned long)pmem - (unsigned long)pool; block /= sizeof(NewDelType); int start = block; int end = block + to_free - 1; assert(start >= 0 && end < psize); printf("%s, freeing block: (%d, %d)\n", __func__, start, end); // Mark it free: for(int i = start; i <= end; ++i){ assert(alloc_map[i] == true); alloc_map[i] = false; }}int main() { NewDelType *pobj1 = 0, *pobj2 = 0, *pobj3 = 0, *pobj4 = 0; printf("%s, NewDelType::pool:(%p ~ %p)\n", __func__, NewDelType::pool, NewDelType::pool + sizeof(NewDelType::pool) - 1); //set_new_handler(out_of_memory); try { pobj1 = new NewDelType;// DelObject (pobj1); cout << endl; pobj2 = new NewDelType[9]; DelObjArray (pobj2); cout << endl;// pobj3 = new NewDelType[5];// cout << endl;//// pobj4 = new NewDelType[6]; } catch(bad_alloc &) { cerr << __func__ << ", Out of memory!" << endl; }}
测试结果: main, NewDelType::pool:(0x6023a0 ~ 0x6023c7) operator new, to use block 0NewDelType, this=0x6023a0, ts=(0x12345678,0x78,0x56,0x34,0x12)operator new [], sz = 44, reqest = 9 operator new [], to use block:(0x6023a4, 1, 9) 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 NewDelType, this=0x6023ac, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023b0, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023b4, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023b8, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023bc, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023c0, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023c4, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023c8, ts=(0x12345678,0x78,0x56,0x34,0x12)NewDelType, this=0x6023cc, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023cc, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023c8, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023c4, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023c0, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023bc, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023b8, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023b4, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023b0, ts=(0x12345678,0x78,0x56,0x34,0x12)~NewDelType, this=0x6023ac, ts=(0x12345678,0x78,0x56,0x34,0x12)operator delete [], pmem:(0x6023a4, 9) 0x9 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x78 0x56 0x34 0x12 operator delete [], freeing block: (1, 9) |