目錄
程序運行前
代碼區
全局區
程序運行后
new
在堆區開辟數據?
delete釋放堆區數據
堆區開辟數組
內存分區模型
棧(Stack)
堆(Heap)
全局/靜態存儲區(Global/Static Storage)
常量存儲區(Constant Storage)
代碼區(Code Area)
程序運行前
在程序編譯后,生成了exe可執行程序,未執行該程序前分為兩個區域
代碼區
存放 CPU 執行的機器指令
代碼區是共享的,共享的目的是對于頻繁被執行的程序,只需要在內存中有一份代碼即可
代碼區是只讀的,使其只讀的原因是防止程序意外地修改了它的指令
全局區
全局變量和靜態變量存放在此.
全局區還包含了常量區, 字符串常量和其他常量也存放在此.
該區域的數據在程序結束后由操作系統釋放
- C++中在程序運行前分為全局區和代碼區
- 代碼區特點是共享和只讀
- 全局區中存放全局變量、靜態變量、常量
- 常量區中存放 const修飾的全局常量 ?和 字符串常量
#include <iostream>
using namespace std;//全局變量
int g_a = 10;
int g_b = 10;//全局常量
const int c_g_a = 10;
const int c_g_b = 10;int main() {//局部變量int a = 10;int b = 10;//靜態變量static int s_a = 10;static int s_b = 10;return 0;
}
程序運行后
不要返回局部變量的地址,棧區開辟的數據由編譯器自動釋放
#include <iostream>
using namespace std;int * func(int a) // 形參也是放在棧區
{int a = 10;return &a; // 不要返回局部變量的地址,棧區開辟的數據由編譯器自動釋放
}int main() {int *p = func();cout << *p << endl; // 10 第一次可以打印這個數字,是因為編譯器做了保留cout << *p << endl; // 隨機值 第二次這個數據就不再保留了return 0;
}
new
利用new關鍵字,可以將數據開辟到堆區
在堆區開辟數據?
int *p = new int(10)
new int(10)表示在堆內存上動態分配了一個int類型的空間,并用值10初始化了該空間。
p指針變量,本質上也是局部變量,放在棧上,指針指向的是所開辟的堆內存區的數據的地址。
int *p = func()
p雖然是在func()函數中聲明的局部變量,但它存儲的是一個指向堆內存的地址。
當函數func()執行完畢后,p雖然在函數棧幀中被銷毀,但指向堆內存的地址仍然存在。
int * func() {/*利用new關鍵字,可以將數據開辟到堆區*/int *p = new int(10); // new當前返回的是int類型的指針,具體什么類型由開辟的數據類型決定return p; // 客觀上返回的是堆區的地址
}int *p = func()/*p雖然是在func()函數中聲明的局部變量,但它存儲的是一個指向堆內存的地址。當函數func()執行完畢后,p雖然在函數棧幀中被銷毀,但指向堆內存的地址仍然存在。
*/
cout << *p << endl; // 10
delete釋放堆區數據
int * func() {int *p = new int(10); return p; }int *p = func();delete p; // 釋放堆區數據cout << *p << endl; // error 內存已經釋放,再次訪問已經是非法操作,報錯
堆區開辟數組
在堆區開辟數組——創建10個整形數據的數組
- new int[10]動態分配一個包含10個int類型元素的數組時,內存管理系統會分配一塊連續的內存空間來存儲這個數組。
- 指針arr存儲的就是這塊內存空間的起始地址,也就是數組的第一個元素的地址。
- 類似于C語言中的數組名
void test() {/*new int[10]動態分配一個包含10個int類型元素的數組時,內存管理系統會分配一塊連續的內存空間來存儲這個數組。指針arr存儲的就是這塊內存空間的起始地址,也就是數組的第一個元素的地址。類似于C語言中的數組名*/int *arr = new int[10]; // 10代表數組有10個元素,注意這里是中括號,不是小括號for (int i = 0; i < 10; i++){arr[i] = i + 100; // 給這10個元素賦值 1000~109 (arr[i] == *(arr + i))}for (int i = 0; i < 10; i++){cout << arr[i] << endl; // 100 ~ 109}//釋放堆區的數組數據內存。數組需要加 []delete[] arr;
}test();
內存分區模型
C++的內存分區模型描述了程序在運行時如何使用系統內存。了解內存分區模型對于理解程序的內存管理和運行效率非常重要!
在一般情況下,C++程序在內存中的布局可以分為以下幾個主要區域:
棧(Stack)
- 棧是用于存儲局部變量、函數參數、函數返回地址以及函數調用時所需的臨時數據的區域。
- 棧的大小在程序運行時是可以動態變化的,通常由系統自動管理。
- 棧內存的分配和釋放是由系統自動完成的,遵循"先進后出"的原則。
堆(Heap)
- 堆被用于存儲動態分配的內存,例如使用
new
和delete
關鍵字來分配和釋放的內存。 - 堆的大小也是動態變化的,可以在程序運行時根據需要進行分配和釋放。
- 程序員通常需要手動管理堆內存的分配和釋放,因此在使用時需要注意內存泄漏和內存溢出的風險。
全局/靜態存儲區(Global/Static Storage)
- 全局變量、靜態變量以及常量通常存儲在這個區域。
- 這部分內存在程序啟動時就被分配,并在程序結束時才被釋放,它們的生命周期與整個程序的生命周期相同。
常量存儲區(Constant Storage)
- 存放常量數據,如字符串常量等。
- 這部分內存通常被固定分配,并且存儲的數據在程序運行期間不會改變。
代碼區(Code Area)
- 存放程序的執行代碼,通常是只讀的。
- 程序的機器指令和函數體都存儲在這個區域。