程式設計中new[]和delete[]應該如何使用?

大雄45發表於2022-10-04
導讀 在平時資料中,我們常看到:new和delete,new[]和delete[]一定要配對使用!有時候不配對使用也不會出現問題。也許你也是隻知其然,不知其所以然,然而我也有點懵了。

在平時資料中,我們常看到:new和delete,new[]和delete[]一定要配對使用!
程式設計中new[]和delete[]應該如何使用?程式設計中new[]和delete[]應該如何使用?
也有人說:有時候不配對使用也不會出現問題。也許你也是隻知其然,不知其所以然,然而我也有點懵了_(¦3」∠)_

那就研究下這個問題:

首先,看下這段配對使用程式碼:

#include#includeusing namespace std;  
class inner {  
   public:  
    inner() { cout << "Constructing" << endl; }  
    ~inner() { cout << "Destructing" << endl; }  
};  
int main(int argc, char *argv[]) {  
    inner *p = new inner();  
    inner *pa = new inner[2];  
    delete p;  
    delete []pa;  
    return 0;  
}  
程式輸出:  
Constructing  
Constructing  
Constructing  
Destructing  
Destructing  
Destructing

因為new[]會建立一個陣列,一個物件陣列需要一定的空間大小,假設一個物件需要N位元組大小,K個物件的陣列就需要K*N個空間來構造物件陣列,但是在delete[]時候,如何知道陣列的長度呢?

所以new[]會在K*N個空間的基礎上,頭部多申請4個位元組,用於儲存陣列長度,這樣delete[]時候才知道物件陣列的大小,才會相應呼叫K次解構函式,並且釋放K*N+4大小的記憶體。

這是我們平時程式設計中經常配對使用的情況,如果不配對使用呢?

new[]與delete結對使用
#include#includeusing namespace std;  
class inner {  
   public:  
    inner() { cout << "Constructing" << endl; }  
    ~inner() { cout << "Destructing" << endl; }  
};  
int main(int argc, char *argv[]) {  
    inner *p = new inner[2];  
    delete p;  
    return 0;  
}  
程式輸出:  
Constructing  
Constructing  
Destructing  
munmap_chunk(): invalid pointer  
Aborted (core dumped)

這裡發現:程式掛掉了。

並且,只呼叫了一次解構函式,為什麼呢?

因為我們使用了delete,delete不同於delete[],它認為這只是一個物件佔用的空間,不是物件陣列,不會訪問前4個位元組獲取長度,所以只呼叫了一次解構函式。而且,最後釋放記憶體的時候只釋放了起始地址為A的記憶體。然而這不是這一整塊記憶體的起始地址,整塊記憶體的起始地址應該是A-4,釋放記憶體如果不從記憶體起始地址操作就會出現斷錯誤,所以導致程式掛掉。

關於記憶體知識可以看我以前的文章:

10張圖22段程式碼,萬字長文帶你搞懂虛擬記憶體模型和malloc內部原理

new和delete[]結對使用
#include#includeusing namespace std;  
class inner {  
   public:  
    inner() { cout << "Constructing" << endl; }  
    ~inner() { cout << "Destructing" << endl; }  
};  
int main(int argc, char *argv[]) {  
    inner *p = new inner();  
    delete []p;  
    return 0; 
} 
程式輸出:  
Constructing  
Destructing  
Destructing  
Destructing  
Destructing  
Destructing  
Destructing  
...  
Destructing  
free(): invalid pointer  
Aborted (core dumped)

這裡呼叫了不定次數的解構函式,並且掛掉,是因為在new時候沒有多申請4個位元組儲存長度,而delete[]時候還會向前找4個位元組獲取長度,這4個位元組是未定義的,所以呼叫了不固定次數的解構函式,釋放記憶體的時候也釋放了起始地址為A-4的記憶體,而正常的起始地址應該是A,所以程式掛掉。

什麼時候可以不配對使用?

我們再來看一段程式碼:

#include#includeusing namespace std;  
int main() {  
    int *pint = new int(5);  
    delete[] pint;  
    int *pinta = new int[4];  
    delete pinta;  
    cout << "success" << endl;  
    return 0;  
}  
程式輸出:  
success

這段程式碼即使不配對使用也會正常執行,這是為什麼呢,因為int是內建型別,new[]和delete[]在配合int使用時知道int是內建型別,不需要解構函式,所以也就不需要多4個位元組來存放陣列長度,只需要直接操作記憶體即可。

原文來自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2848347/,如需轉載,請註明出處,否則將追究法律責任。

相關文章