delete p和delete p的區別

2021-05-10 09:32:27 字數 3204 閱讀 2607

原文:

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...