重载类的 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 <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <new>
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<typename T>
inline void DelObject(T *&pobj){
delete pobj;
pobj = 0; // Don't forget to assigne pobj as 0.
}
template<typename T>
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<NewDelType>(pobj1);
cout << endl;
pobj2 = new NewDelType[9];
DelObjArray<NewDelType>(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 [], sz = 44, reqest = 9 |
转载于:https://blog.51cto.com/frankniefaquan/1939159