重载类的 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,如需转载请自行联系原作者