【C++】動態記憶體分配詳解(new/new[]和delete/delete[])
一、為什麼需要動態記憶體分配?
在C++程式中,所有記憶體需求都是在程式執行之前通過定義所需的變數來確定的。 但是可能存在程式的記憶體需求只能在執行時確定的情況。 例如,當需要的記憶體取決於使用者輸入。 在這些情況下,程式需要動態分配記憶體,C ++語言將運算子new和delete合成在一起。
(1)特點
1.C++中通過new關鍵字進行動態記憶體申請 |
2.C++中的動態記憶體分配是基於型別進行的 |
3.delete關鍵字用於記憶體釋放 |
(2)語法
①變數申請:
Type* pointer = new Type;
//...
delete pointer;
表示式用於分配記憶體以包含一個型別型別的單個元素。
②陣列申請:
Type* pointer = new Type[N];
//...
delete[] pointer;
表示用於分配型別型別的元素的塊(陣列),其中N是表示這些元素的量的整數值。
Example:
int * foo;
foo = new int [5];
在這種情況下,系統為int型別的五個元素動態分配空間,並返回指向序列的第一個元素的指標,該指標被分配給foo(指標)。 因此,foo現在指向一個有效的記憶體塊,其中包含五個int型別元素的空間。
這裡,foo是一個指標,因此,foo指向的第一個元素可以使用表示式foo [0]或表示式* foo(兩者都是等價的)來訪問。可以使用foo [1]或*(foo + 1)訪問第二個元素,依此類推......
Note:
我們程式請求的動態記憶體由系統從記憶體堆中分配。 但是,計算機記憶體是一種有限的資源,它可能會耗盡。 因此,無法保證所有使用operator new分配記憶體的請求都將由系統授予。
(3)動態記憶體分配Example:
#include <stdio.h> int main() { int* p = new int; *p = 5; *p = *p + 10; printf("p = %p\n", p); printf("*p = %d\n", *p); delete p; p = new int[10]; for(int i=0; i<10; i++) { p[i] = i + 1; printf("p[%d] = %d\n", i, p[i]); } delete[] p; return 0; }
編譯執行,結果:
p = 007F77D8
*p = 15
p[0] = 1
p[1] = 2
p[2] = 3
p[3] = 4
p[4] = 5
p[5] = 6
p[6] = 7
p[7] = 8
p[8] = 9
p[9] = 10
請按任意鍵繼續. . .
二、new關鍵字與malloc函式的區別
new關鍵字是C++的一部分 | malloc是由C庫提供的函式 |
new以具體型別為單位進行記憶體分配 | malloc以位元組為單位進行記憶體分配 |
new在申請單個型別變數時可進行初始化 | malloc不具備記憶體初始化的特性 |
三、new關鍵字的初始化:
int* pi = new int(1);
float* pf = new float(2.0f);
char* pc = new char('c');
Test:
#include <stdio.h>
int main()
{
int* pi = new int(1);
// int* pa = new int[1];
float* pf = new float(2.0f);
char* pc = new char('c');
printf("*pi = %d\n", *pi);
printf("*pf = %f\n", *pf);
printf("*pc = %c\n", *pc);
delete pi;
delete pf;
delete pc;
return 0;
}
輸出結果:
*pi = 1
*pf = 2.000000
*pc = c
請按任意鍵繼續. . .
注意:
int* pi = new int(1); | 表示動態分配一個int ,初始化為 1 |
int* pa = new int[1]; | 表示動態分配一個數組,陣列大小為1 |
四、C++動態分配記憶體異常機制
事項一下,我們的計算機記憶體優先,如果我們分配一個很大的記憶體空間,會出現棧滿,程式產生異常,程式崩潰。所以我們需要引入異常機制。
C ++提供了兩種標準機制來檢查分配是否成功。
(1)一個是處理異常。
使用此方法,在分配失敗時丟擲bad_alloc型別的異常。 例外是這些教程後面解釋的強大的C ++特性。 但是現在,您應該知道如果丟擲此異常並且未由特定處理程式處理,則程式執行將終止。
此異常方法是new預設使用的方法,並且是在宣告中使用的方法,like:
foo = new int [5]; // if allocation fails, an exception is thrown
(2)另一種方法稱為nothrow
當使用它時會發生的情況是,當記憶體分配失敗時,而不是丟擲bad_alloc異常或終止程式,new返回的指標是空指標,程式繼續正常執行 。
可以使用名為nothrow的特殊物件(在header <new>中宣告)作為new的引數來指定此方法:
foo = new (nothrow) int [5];
在這種情況下,如果此記憶體塊的分配失敗,則可以通過檢查foo是否為空指標來檢測異常:
int * foo;
foo = new (nothrow) int [5];
if (foo == nullptr) {
// error assigning memory. Take measures.
}
異常處理Example:
// rememb-o-matic
#include <iostream>
#include <new>
using namespace std;
int main ()
{
int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int[i];
if (p == nullptr)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
編譯執行,結果:
<全文完>
參考資料:
2)C++官網