原文:
operator new 和 operator delete函式有兩個過載版本,每個版本支援相關的new表示式和delete表示式:
void* operator new (size_t); // allocate an object
void* operator new (size_t); // allocate an array
void operator delete (void*); // free an oject
void operator delete (void*); // free an array
熟悉c的朋友看到這裡可能會很奇怪:
在c中釋放記憶體用free(void *)【注意這裡只有乙個引數void *】
為什麼到了c++裡會出現兩個!按理說delete 會呼叫free釋放記憶體的啊?
另外delete 是如何知道刪除的物件個數的?
另外一般的教材比如《高質量c++程式設計指南》都會這麼說:
在用delete 釋放物件陣列時,留意不要丟了符號『』。例如
delete objects; // 正確的用法
delete objects; // 錯誤的用法
後者相當於delete objects[0],漏掉了另外99 個物件
這樣的描述當然是錯誤的,而且會誤導觀眾
為了解決問題,開啟vc6,輸入以下**:
class
avoid
d(a *);
intmain(
intargc,
char
*argv)
void
d(a *p)
執行結果:debug assertion failed!
咦,不是說等同於delete p[0]嗎?
為了看看究竟,只好動用那多年以前就忘光了的彙編
經過一番折騰,最後連猜帶蒙得出下面的觀點:
1 如果物件無析構函式(包括不需要合成析構函式,比如注釋掉~a和string s兩行**)
delete會直接呼叫operator delete並直接呼叫free釋放記憶體
這個時候的
new=new (僅在數量上有差異),delete=delete
2 如果物件存在析構函式(包括合成析構函式),則【這個才是重點】:
new 返回的位址會後移4個位元組,並用那4個存放陣列的大小!而new不用後移這四個位元組
delete根據那個4個位元組的值,呼叫指定次數的析構函式 ,同樣delete也不需要那四個位元組
結果就是在不恰當的使用delete 和delete 呼叫free的時候會造成4個位元組的錯位,最終導致debug assertion failed!
再回到《高質量c++程式設計指南》:
delete objects; // 正確的用法
delete objects; // 錯誤的用法
後者相當於delete objects[0],漏掉了另外99 個物件
嚴格應該這樣說:後者相當於僅呼叫了objects[0]的析構函式,漏掉了呼叫另外99 個物件的析構函式,並且在呼叫之後釋放記憶體時導致異常(如果存在析構函式的話),如果物件無析構函式該語句與delete objects相同
注:1 測試環境vc6
2 不保證觀點正確
3 歡迎指正
由new分配的乙個陣列空間,比如說 int *array=new int[50],當用delete釋放這個空間時,用語句delete array和delete array是否等價!
c++告訴我們在**用 new 分配的單個物件的記憶體空間的時候用 delete,**用 new 分配的一組物件的記憶體空間的時候用 delete。
關於 new 和 delete,其中又分為兩種情況:(1) 為基本資料型別分配和**空間;(2) 為自定義型別分配和**空間。
對於 (1),上面提供的程式a可以證明了 delete 和 delete 是等同的。
程式a:
#include
#define buff_size 10240
int main(int argc, char *argv)
return 0;
} 但是對於 (2),情況就發生了變化。請看下面的程式。
#include
#define buff_size 10240
class ttt
; ~ttt()
; private:
int a;
char* aa;
int inta[1024];
}; int main(int argc, char *argv)
return 0;
} 大家可以自己執行這個程式,看一看 delete p1 和 delete p1 的不同結果,我就不在這裡貼執行結果了。
從執行結果中我們可以看出,delete p 在**空間的過程中,只有 p[0] 這個物件呼叫了析構函式,其它物件如 p[1]、p[2] 等都沒有呼叫自身的析構函式,在析構函式中的記憶體釋放操作將不會被執行(引發記憶體洩漏),已使用記憶體不斷增加,這就是問題的癥結所在。如果用 delete,則在**空間之前所有物件都會首先呼叫自己的析構函式,已使用記憶體不會不斷增加。
基本型別的物件沒有析構函式,所以**基本型別組成的陣列空間用 delete 和 delete 都是應該可以的;但是對於類物件陣列,只能用 delete。對於 new 的單個物件,只能用 delete 不能用 delete **空間。
#include ;
#include "xercesc/dom/dom.hpp"
int main()
~t()
};int main()
大家可以自己執行這個程式,看一看 delete p1 和 delete p1 的不同結果,我就不在這裡貼執行結果了。
從執行結果中我們可以看出,delete p1 在**空間的過程中,只有 p1[0] 這個物件呼叫了析構函式,其它物件如 p1[1]、p1[2] 等都沒有呼叫自身的析構函式,這就是問題的癥結所在。如果用 delete,則在**空間之前所有物件都會首先呼叫自己的析構函式。
基本型別的物件沒有析構函式,所以**基本型別組成的陣列空間用 delete 和 delete 都是應該可以的;但是對於類物件陣列,只能用 delete。對於 new 的單個物件,只能用 delete 不能用 delete **空間。
所以乙個簡單的使用原則就是:new 和 delete、new 和 delete 對應使用。
delete p與delete p 的區別
operator new 和 operator delete函式有兩個過載版本,每個版本支援相關的new表示式和delete表示式 void operator new size t allocate an object void operator new size t allocate an arr...
和 區別和聯絡, 和 區別和聯絡
和 區別和聯絡,和 區別和聯絡,實際專案中,什麼情況用哪種?首先,和 的聯絡 共同點 和 都可以用作 邏輯與 運算子,都是雙目運算子。具體要看使用時的具體條件來決定。無論使用哪種運算子,對最終的運算結果都沒有影響。情況1 當上述的運算元是boolean型別變數時,和 都可以用作邏輯與運算子。情況2 ...
rpx和樣式和class和flex
5 style 靜態的樣式統一寫到 class 中。style 接收動態的樣式,在執行時會進行解析,請盡量避免將靜態的樣式寫進 style 中,以免影響渲染速度。例 6 class 用於指定樣式規則,其屬性值是樣式規則中類選擇器名 樣式類名 的集合,樣式類名不需要帶上.樣式類名之間用空格分隔。關於f...