重载类的 new,delete,new[],delete[] 运算符成员函数

本文介绍如何重载C++中的new和delete运算符来控制内存分配与释放过程。通过自定义NewDelType类实现new、delete、new[]及delete[]的重载,并提供了一段示例代码展示其工作原理。

重载类的 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_tthrow(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_tthrow(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, to use block 0
NewDelType,  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)





      本文转自FrankNie0101 51CTO博客,原文链接:http://blog.51cto.com/frankniefaquan/1939159,如需转载请自行联系原作者









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值