重载类的 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);
重载时必须与原型一致!
请看示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#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 |
本文转自FrankNie0101 51CTO博客,原文链接:http://blog.51cto.com/frankniefaquan/1939159,如需转载请自行联系原作者