天天看點

重載類的 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);

重載時必須與原型一緻!

請看示例代碼:

<code>#include &lt;cstddef&gt;</code>

<code>#include &lt;cstdio&gt;</code>

<code>#include &lt;cstdlib&gt;</code>

<code>#include &lt;cassert&gt;</code>

<code>#include &lt;iostream&gt;</code>

<code>#include &lt;new&gt;</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 &lt;&lt; "memory exhausted!\n";</code>

<code>//  exit(-1);</code>

<code>//}</code>

<code>template</code><code>&lt;</code><code>typename</code> <code>T&gt;</code>

<code>inline</code> <code>void</code> <code>DelObject(T *&amp;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 *&amp;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 &lt; 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 &gt;= 0 &amp;&amp; block &lt; psize &amp;&amp; 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 &gt;= 0 &amp;&amp; request &lt;= 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 &lt; 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 &lt;= 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 &lt; 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 &lt; 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 &gt;= 0 &amp;&amp; end &lt; 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 &lt;= 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&lt;NewDelType&gt;(pobj1);</code>

<code>    </code><code>cout &lt;&lt; endl;</code>

<code>    </code><code>pobj2 = </code><code>new</code> <code>NewDelType[9];</code>

<code>    </code><code>DelObjArray&lt;NewDelType&gt;(pobj2);</code>

<code>//    pobj3 = new NewDelType[5];</code>

<code>//    cout &lt;&lt; endl;</code>

<code>//</code>

<code>//    pobj4 = new NewDelType[6];</code>

<code>  </code><code>} </code><code>catch</code><code>(bad_alloc &amp;) {</code>

<code>    </code><code>cerr &lt;&lt; __func__ &lt;&lt; </code><code>", Out of memory!"</code> <code>&lt;&lt; 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,如需轉載請自行聯系原作者

繼續閱讀