在 C++ 中,內存管理是核心課題之一。根據內存開闢的時間和方式,主要可以分為靜態內存開闢(通常涉及棧空間和全局/靜態區)和動態內存開闢(堆空間)。


1. 靜態內存開闢

靜態內存開闢是指在編譯階段就確定了大小,並在程序運行到對應作用域時由系統自動分配和釋放的內存。

  • 存儲位置:主要在棧 (Stack)全局/靜態存儲區
  • 分配時機:編譯時確定大小,運行時進入作用域(如函數調用)即分配。
  • 管理方式:由編譯器/系統自動管理,程序員不需要手動釋放。
  • 特點:分配效率極高,但空間相對有限。

示例代碼:

int a = 10;            // 局部變量,在棧上開闢
static int b = 20;     // 靜態變量,在全局/靜態區開闢
int arr[100];          // 數組大小必須是常量,編譯時確定
void staticlloc() {
	int arr[5];
	int i = 0;
	for (; i < 5; i++)
	{
		arr[i] = i + 1;
		printf("%d, %p\n", *(arr + i), arr + i);
	}
}

// 重點:內存開闢
int main() {
	// Stack overflow 棧溢出 , 將10 改為 0.1 才能正常運行
	// int arr[(int)(10 * 1024 * 1024)]; // 棧區開闢, 10M數組大小,int四字節,40M空間

	// c有分區,四驅模型,棧,堆
	// 棧:佔用內存空間最大值 1M,開闢內存的方式是靜態內存開闢,方法結束會自動回收
	// 堆:佔用內存空間最大值 80%,開闢內存的方式是動態內存開闢,方法結束不會自動回收,必須手動回收

	staticlloc();
	return 0;
}

輸出:

1, 0000009018BEFA78                                                                                                     
2, 0000009018BEFA7C                                                                                                     
3, 0000009018BEFA80                                                                                                     
4, 0000009018BEFA84                                                                                                     
5, 0000009018BEFA88

2. 動態內存開闢

動態內存開闢是指在程序運行過程中,根據實際需要申請的內存。

  • 存儲位置堆 (Heap)
  • 分配時機:運行時根據需求申請。
  • 管理方式:程序員通過特定關鍵字(new / delete)或函數(malloc / free)手動管理。
  • 特點:靈活性高,可以申請非常大的空間;但如果忘記釋放,會導致內存泄漏

示例代碼:

int* p = new int;       // 在堆上申請一個 int 空間
int* arr = new int[n];  // n 可以是運行時的變量

delete p;               // 必須手動釋放
delete[] arr;           // 數組釋放需要加 []

C語言動態開闢方式 malloc

雖然 C++ 兼容 malloc,但在 C++ 開發中,new 幾乎在所有場景下都取代了 malloc。以下是它們的詳細對比以及為什麼 C++ 開發者更傾向於使用 new

特性

malloc / free

new / delete

屬性

庫函數 (Standard Library)

運算符 (Keyword/Operator)

構造函數

不調用。只負責分塊內存。

自動調用。開闢後立即初始化對象。

返回類型

返回 void*,必須強制類型轉換。

返回對應類型的指針,類型安全

計算大小

需手動計算字節數(如 sizeof(int))。

編譯器根據類型自動計算大小。

內存失敗

分配失敗返回 NULL

分配失敗默認拋出異常 (bad_alloc)。

適用範圍

常用於 C 代碼或底層內存池開發。

C++ 對象的標準分配方式。

示例代碼:

void dynamicalloc() {
	int* p = (int*)malloc(sizeof(int) * 5); // 堆區開闢
	if (p == NULL) {
		printf("內存開闢失敗\n");
		return;
	}
	int i = 0;
	for (; i < 5; i++)
	{
		*(p + i) = i + 1;
		printf("%d, %p\n", *(p + i), p + i);
	}
	// 回收內存
	free(p);
	p = NULL; // 野指針
}

// 動態內存開闢
int main() {
	// 堆區開闢
	int* p = (int*)malloc(sizeof(int) * (10 * 1024 * 1024)); // 40M空間
	if (p == NULL) {
		printf("內存開闢失敗\n");
		return -1;
	}
	
	// 使用內存
	int i = 0;
	for (; i < 10 * 1024 * 1024; i++)
	{
		*(p + i) = i + 1;
	}
	// 回收內存
	free(p);
	p = NULL; // 野指針
	while (true) {
		Sleep(100);
	}
	return 0;
}