在C++中,我們經常需要處理數據的存儲問題。有時候,我們可能不知道需要多少內存,或者需要根據程序運行時的情況來動態調整內存大小。這時候,靜態內存分配(比如直接定義變量)就不夠用了,這就需要用到動態內存分配。
爲什麼需要動態內存分配?¶
我們平時寫代碼時,靜態內存分配(比如 int a; 或 char s[20];)是在編譯時就確定了內存大小,由編譯器自動管理。但如果遇到這樣的場景:需要存儲一組不確定數量的數據(比如用戶輸入的多個數字),或者臨時需要一塊很大的內存,靜態內存就顯得不夠靈活了。
動態內存分配允許我們在運行時根據實際需求向“堆”申請內存,使用完後再手動釋放。堆是一塊獨立的內存區域,大小相對靈活,但需要我們自己負責管理,避免內存泄漏。
動態內存與堆/棧的簡單區別¶
- 棧(Stack):由編譯器自動分配和釋放,用於存儲局部變量、函數參數等,內存大小有限且速度快。
- 堆(Heap):程序運行時動態申請的內存區域,大小靈活但由程序員手動管理,需要顯式釋放。
new 和 delete 就是用來操作堆內存的核心工具。
new 操作符:在堆上分配內存¶
要在堆上申請內存,我們使用 new 操作符。它的語法很簡單:
1. 分配單個對象¶
類型* 指針變量 = new 類型; // 分配一個該類型的內存空間
例如,分配一個 int 類型的動態變量:
int* p = new int; // p 指向堆上一個 int 類型的內存空間
此時,p 是一個指針,我們可以通過 *p 訪問或修改這塊內存的值:
*p = 100; // 將 100 存入 p 指向的內存
cout << "動態變量的值:" << *p << endl; // 輸出 100
如果需要在分配時初始化內存,可以直接在 new 後加括號傳入初始值:
int* num = new int(20); // 直接初始化爲 20
cout << "初始化後的變量:" << *num << endl; // 輸出 20
2. 分配數組¶
如果需要一組數據(比如數組),可以用 new[] 來分配:
類型* 數組指針 = new 類型[數組大小]; // 分配數組內存
例如,分配一個包含 5 個 int 的動態數組:
int* arr = new int[5]; // arr 指向一個有 5 個 int 的數組
數組元素默認不初始化(值可能是隨機的),如果需要初始化(比如全爲 0),可以寫成:
int* arr = new int[5](); // 每個元素被初始化爲 0
使用數組時,可以通過下標訪問元素:
for (int i = 0; i < 5; ++i) {
arr[i] = i * 2; // 數組賦值:0, 2, 4, 6, 8
}
// 打印數組元素
for (int i = 0; i < 5; ++i) {
cout << "arr[" << i << "] = " << arr[i] << endl;
}
delete 操作符:釋放堆內存¶
new 分配的內存不會自動釋放,必須用 delete 或 delete[] 手動釋放,否則會導致內存泄漏(程序佔用的內存越來越多,最終崩潰)。
1. 釋放單個對象¶
如果用 new 分配了單個對象,用 delete 釋放:
int* p = new int(100);
// 使用完後釋放內存
delete p; // p 指向的堆內存被釋放,之後不能再用 *p
2. 釋放數組¶
如果用 new[] 分配了數組,必須用 delete[] 釋放,否則只會釋放數組第一個元素的內存,導致內存泄漏:
int* arr = new int[5];
// 使用完後釋放數組
delete[] arr; // 必須用 delete[],不能用 delete!
常見錯誤與注意事項¶
- 忘記釋放內存:用
new分配後不delete,會導致內存泄漏。例如:
int* p = new int(5);
// 使用 p...
// 忘記寫 delete p; 這裏內存會一直佔用
- 數組用
delete而非delete[]:例如:
int* arr = new int[10];
delete arr; // 錯誤!應該用 delete[] arr;
這樣只會釋放數組第一個元素的內存,剩下的 9 個元素內存永遠不會被釋放。
- 重複釋放內存:同一個指針不能
delete兩次,否則會導致程序崩潰:
int* p = new int;
delete p;
delete p; // 錯誤!重複釋放,未定義行爲
總結¶
動態內存分配讓我們可以在運行時靈活管理內存,核心工具是 new 和 delete:
- new 用於在堆上分配單個對象或數組內存,語法分別爲 new 類型 和 new 類型[大小];
- delete 用於釋放單個對象的內存,delete[] 用於釋放數組的內存;
- 務必用對應方式釋放內存(單個對象用 delete,數組用 delete[]),避免內存泄漏或程序崩潰。
合理使用動態內存,可以讓程序更高效地利用內存資源,但要時刻注意內存的分配與釋放,養成良好的編程習慣。