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









相关文章
|
2月前
|
存储 算法 编译器
【C++ 内存管理 重载new/delete 运算符 新特性】深入探索C++14 新的/删除的省略(new/delete elision)的原理与应用
【C++ 内存管理 重载new/delete 运算符 新特性】深入探索C++14 新的/删除的省略(new/delete elision)的原理与应用
59 0
|
3月前
|
安全 编译器 C语言
深入了解C++:形参、内联、重载、引用、const和指针、new和delete
深入了解C++:形参、内联、重载、引用、const和指针、new和delete
22 1
|
4月前
|
C++
C++类中的const使用
C++类中的const使用
|
10月前
|
C++
Date类实现运算符和赋值重载
Date类实现运算符和赋值重载
解决办法:对‘operator delete(void*)’未定义的引用
解决办法:对‘operator delete(void*)’未定义的引用
137 0
尽量以non-member non-friend函数替换成员函数
尽量以non-member non-friend函数替换成员函数
130 0
|
Java 编译器
重载(overload) 和重写(override) 的区别?重载的方法能否根据返回类型进行区分?
重载(overload) 和重写(override) 的区别?重载的方法能否根据返回类型进行区分?
1190 0
详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
339 0