重载类的 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);
重载时必须与原型一致!
请看示例代码:
<code>#include <cstddef></code>
<code>#include <cstdio></code>
<code>#include <cstdlib></code>
<code>#include <cassert></code>
<code>#include <iostream></code>
<code>#include <new></code>
<code>using</code> <code>std::cout;</code>
<code>using</code> <code>std::endl;</code>
<code>using</code> <code>std::cerr;</code>
<code>using</code> <code>std::bad_alloc;</code>
<code>using</code> <code>std::hex;</code>
<code>//void out_of_memory(){</code>
<code>// cerr << "memory exhausted!\n";</code>
<code>// exit(-1);</code>
<code>//}</code>
<code>template</code><code><</code><code>typename</code> <code>T></code>
<code>inline</code> <code>void</code> <code>DelObject(T *&pobj){</code>
<code> </code><code>delete</code> <code>pobj;</code>
<code> </code><code>pobj = 0; </code><code>// Don't forget to assigne pobj as 0.</code>
<code>}</code>
<code>inline</code> <code>void</code> <code>DelObjArray(T *&parr) {</code>
<code> </code><code>delete</code> <code>[]parr;</code>
<code> </code><code>parr = 0; </code><code>// Don't forget to assigne parr as 0.</code>
<code>class</code> <code>NewDelType {</code>
<code> </code><code>union</code> <code>{</code>
<code> </code><code>unsigned </code><code>char</code> <code>ch[4];</code>
<code> </code><code>int</code> <code>val;</code>
<code> </code><code>}ts;</code>
<code>public</code><code>:</code>
<code> </code><code>enum</code> <code>{ psize = 10 };</code>
<code> </code><code>static</code> <code>unsigned </code><code>char</code> <code>pool[];</code>
<code> </code><code>static</code> <code>bool</code> <code>alloc_map[];</code>
<code> </code><code>NewDelType() { </code>
<code> </code><code>ts.val = 0x12345678; </code>
<code> </code><code>printf</code><code>(</code><code>"%s, this=%p, ts=(%#x,%#x,%#x,%#x,%#x)\n"</code><code>, __func__,</code><code>this</code><code>,ts.val,ts.ch[0],ts.ch[1],ts.ch[2],ts.ch[3]);</code>
<code> </code><code>}</code>
<code> </code><code>~NewDelType() { </code>
<code> </code><code>printf</code><code>(</code><code>"%s, this=%p, ts=(%#x,%#x,%#x,%#x,%#x)\n"</code><code>, __func__,</code><code>this</code><code>,ts.val,ts.ch[0],ts.ch[1],ts.ch[2],ts.ch[3]);</code>
<code> </code><code>void</code><code>* operator </code><code>new</code><code>(</code><code>size_t</code><code>) </code><code>throw</code><code>(bad_alloc);</code>
<code> </code><code>void</code> <code>operator </code><code>delete</code><code>(</code><code>void</code><code>* pmem);</code>
<code> </code><code>void</code><code>* operator </code><code>new</code><code>[](</code><code>size_t</code> <code>sz) </code><code>throw</code><code>(bad_alloc);</code>
<code> </code><code>void</code> <code>operator </code><code>delete</code><code>[](</code><code>void</code><code>* pmem);</code>
<code>};</code>
<code>unsigned </code><code>char</code> <code>NewDelType::pool[psize * </code><code>sizeof</code><code>(NewDelType)];</code>
<code>bool</code> <code>NewDelType::alloc_map[psize] = {</code><code>false</code><code>};</code>
<code>void</code><code>* NewDelType::operator </code><code>new</code><code>(</code><code>size_t</code><code>) </code><code>throw</code><code>(bad_alloc) {</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i = 0; i < psize; i++){</code>
<code> </code><code>if</code><code>(!alloc_map[i]) {</code>
<code> </code><code>printf</code><code>(</code><code>"%s, to use block %d\n"</code><code>, __func__, i);</code>
<code> </code><code>alloc_map[i] = </code><code>true</code><code>; </code><code>// Mark it used</code>
<code> </code><code>return</code> <code>pool + (i * </code><code>sizeof</code><code>(NewDelType));</code>
<code> </code><code>}</code>
<code> </code><code>printf</code><code>(</code><code>"%s, to throw bad_alloc\n"</code><code>, __func__);</code>
<code> </code><code>throw</code> <code>bad_alloc();</code>
<code>void</code> <code>NewDelType::operator </code><code>delete</code><code>(</code><code>void</code><code>* pmem) {</code>
<code> </code><code>// Check for null pointer</code>
<code> </code><code>if</code><code>(!pmem){</code>
<code> </code><code>printf</code><code>(</code><code>"%s, null pointer\n"</code><code>, __func__);</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>// Assume it was created in the pool</code>
<code> </code><code>// Calculate which block number it is:</code>
<code> </code><code>unsigned </code><code>long</code> <code>block = (unsigned </code><code>long</code><code>)pmem - (unsigned </code><code>long</code><code>)pool;</code>
<code> </code><code>block /= </code><code>sizeof</code><code>(NewDelType);</code>
<code> </code><code>printf</code><code>(</code><code>"%s, freeing block:(%p, %lu)\n"</code><code>, __func__, pmem, block);</code>
<code> </code><code>assert</code><code>(block >= 0 && block < psize && alloc_map[block] == </code><code>true</code><code>);</code>
<code> </code><code>// Mark it free:</code>
<code> </code><code>alloc_map[block] = </code><code>false</code><code>;</code>
<code>void</code><code>* NewDelType::operator </code><code>new</code><code>[](</code><code>size_t</code> <code>sz) </code><code>throw</code><code>(bad_alloc) {</code>
<code> </code><code>assert</code><code>( (sz - 8) % </code><code>sizeof</code><code>(NewDelType) == 0);</code>
<code> </code><code>int</code> <code>request = (sz - 8) / </code><code>sizeof</code><code>(NewDelType);</code>
<code> </code><code>assert</code><code>(request >= 0 && request <= psize);</code>
<code> </code><code>printf</code><code>(</code><code>"%s, sz = %lu, reqest = %d\n"</code><code>, __func__, sz, request);</code>
<code> </code><code>int</code> <code>avail = 0;</code>
<code> </code><code>int</code> <code>start = -1, end = -1;</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i = 0; i < psize; ++i){</code>
<code> </code><code>if</code><code>(alloc_map[i] == </code><code>false</code><code>)</code>
<code> </code><code>++avail;</code>
<code> </code><code>else</code>
<code> </code><code>avail = 0;</code>
<code> </code><code>if</code><code>(avail == request){</code>
<code> </code><code>end = i;</code>
<code> </code><code>start = end + 1 - request;</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>if</code><code>(avail == request){</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>j = start; j <= end; ++j){</code>
<code> </code><code>alloc_map[j] = </code><code>true</code><code>; </code>
<code> </code><code>unsigned </code><code>char</code> <code>*pbyte = pool + start * </code><code>sizeof</code><code>(NewDelType);</code>
<code> </code><code>printf</code><code>(</code><code>"%s, to use block:(%p, %d, %d)\n"</code><code>, __func__, pbyte, start, end);</code>
<code> </code><code>printf</code><code>(</code><code>"\t"</code><code>);</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>k = 0; k < 12; ++k){</code>
<code> </code><code>printf</code><code>(</code><code>"0x%x "</code><code>, pbyte[k]);</code>
<code> </code><code>printf</code><code>(</code><code>"\n"</code><code>);</code>
<code> </code><code>return</code> <code>pbyte;</code>
<code> </code><code>else</code><code>{</code>
<code> </code><code>printf</code><code>(</code><code>"%s, to throw bad_alloc, avail = %d\n"</code><code>, __func__, avail);</code>
<code> </code><code>throw</code> <code>bad_alloc();</code>
<code>void</code> <code>NewDelType::operator </code><code>delete</code><code>[](</code><code>void</code><code>* pmem) {</code>
<code> </code><code>//The quantity of objects allocated was saved in the first byte.</code>
<code> </code><code>//WARNING: Maybe the quantity is not saved here for every case. </code>
<code> </code><code>unsigned </code><code>char</code> <code>to_free = *(unsigned </code><code>char</code> <code>*)pmem;</code>
<code> </code><code>printf</code><code>(</code><code>"%s, pmem:(%p, %d)\n"</code><code>, __func__, pmem, to_free);</code>
<code> </code><code>printf</code><code>(</code><code>"\t"</code><code>);</code>
<code> </code><code>unsigned </code><code>char</code> <code>*pbyte = (unsigned </code><code>char</code> <code>*)pmem;</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>k = 0; k < 12; ++k){</code>
<code> </code><code>printf</code><code>(</code><code>"0x%x "</code><code>, pbyte[k]);</code>
<code> </code><code>printf</code><code>(</code><code>"\n"</code><code>);</code>
<code> </code><code>int</code> <code>start = block;</code>
<code> </code><code>int</code> <code>end = block + to_free - 1;</code>
<code> </code><code>assert</code><code>(start >= 0 && end < psize);</code>
<code> </code><code>printf</code><code>(</code><code>"%s, freeing block: (%d, %d)\n"</code><code>, __func__, start, end);</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i = start; i <= end; ++i){</code>
<code> </code><code>assert</code><code>(alloc_map[i] == </code><code>true</code><code>);</code>
<code> </code><code>alloc_map[i] = </code><code>false</code><code>;</code>
<code>int</code> <code>main() {</code>
<code> </code><code>NewDelType *pobj1 = 0, *pobj2 = 0, *pobj3 = 0, *pobj4 = 0;</code>
<code> </code><code>printf</code><code>(</code><code>"%s, NewDelType::pool:(%p ~ %p)\n"</code><code>, __func__, NewDelType::pool, NewDelType::pool + </code><code>sizeof</code><code>(NewDelType::pool) - 1);</code>
<code> </code><code>//set_new_handler(out_of_memory);</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>pobj1 = </code><code>new</code> <code>NewDelType;</code>
<code>// DelObject<NewDelType>(pobj1);</code>
<code> </code><code>cout << endl;</code>
<code> </code><code>pobj2 = </code><code>new</code> <code>NewDelType[9];</code>
<code> </code><code>DelObjArray<NewDelType>(pobj2);</code>
<code>// pobj3 = new NewDelType[5];</code>
<code>// cout << endl;</code>
<code>//</code>
<code>// pobj4 = new NewDelType[6];</code>
<code> </code><code>} </code><code>catch</code><code>(bad_alloc &) {</code>
<code> </code><code>cerr << __func__ << </code><code>", Out of memory!"</code> <code><< endl;</code>
测试结果:
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,如需转载请自行联系原作者