C++ 面向對象程序設計–內存分區詳解
一、分區的意義
在講分區前,先談談內存分區的意義,也就是為什麼程序要進行分區?
筆者認為這是為瞭編程的靈活性,因為將內存分區後,不同區域的內存,相關的數據就有的不同的生命周期。以筆者之前的一篇算法復雜度的blog中提到棧幀空間為例,在此就是指棧區,而棧區多指非main函數調用的內存(相關參數等),當非main函數調用結束後,這塊的內存就會清空釋放。而這裡的數據就可以和在main函數中的數據有不同的生命周期。
二、代碼區
1、定義
存放函數體內的二進制代碼,由操作系統進行管理
註意:代碼區是在程序運行前的內存區域,除瞭代碼區,運行前還有全局區。代碼區存放的二進制代碼其實就是編譯器(cpu)執行的指令。
2、特點
1)代碼區是共享的,之所以共享是因為對於被頻繁執行的程序,隻需要在內存中存放一份代碼即可。避免內存過多的浪費。
2)代碼區是隻讀的,原因是防止程序意外地修改瞭它的指令。
三、全局區
前面提到全局區,也在程序執行前。
1、定義
存放全局變量和靜態變量以及常量
2、特點
該區域的數據在程序結束後由操作系統釋放。
3、相關代碼
1)全局變量
#include<iostream> #include<string> using namespace std; // 全局變量 int g_a = 10; int g_b = 10; int main() { // 全局區 // 全局變量、靜態變量、常量 // 創建普通局部變量 int a = 10; int b = 10; cout << "局部變量a的地址為: " << (int)&a << endl << "局部變量b的地址為: " << (int)&b << endl; cout << "全局變量g_a的地址為: " << (int)&g_a << endl; cout << "全局變量g_b的地址為: " << (int)&g_b << endl; system("pause"); return 0; }
程序執行結果:
從結果看,局部變量和全局變量存放的地址顯然有很大的不同,而從a和b以及g_a和g_b的地址來看,全局變量和局部變量相鄰的變量的內存地址是相近,從結果看是差瞭4,這是因為單位int占4個字節。
2)靜態變量
// 靜態變量 在普通變量前面加static,屬於靜態變量 static int s_a = 10; static int s_b = 10; cout << "靜態變量s_a的地址為: " << (int)&s_a << endl; cout << "靜態變量s_b的地址為: " << (int)&s_b << endl;
將上述代碼加入到前面的main函數中,運行得到如下結果
3)常量(不包含局部常量即const修飾的局部變量)
#include<iostream> #include<string> 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; cout << "局部變量a的地址為: " << (int)&a << endl << "局部變量b的地址為: " << (int)&b << endl; cout << "全局變量g_a的地址為: " << (int)&g_a << endl; cout << "全局變量g_b的地址為: " << (int)&g_b << endl; // 靜態變量 在普通變量前面加static,屬於靜態變量 static int s_a = 10; static int s_b = 10; cout << "靜態變量s_a的地址為: " << (int)&s_a << endl; cout << "靜態變量s_b的地址為: " << (int)&s_b << endl; // 常量 // 字符串常量 cout << "字符串常量的地址為: " << (int)&"hello world" << endl; //const修飾的變量 // const修飾的全局變量、const修飾的局部變量 cout << "全局常量c_g_a的地址為: " << (int)&c_g_a << endl; cout << "全局常量c_g_b的地址為: " << (int)&c_g_b << endl; // 局部常量 const int c_l_a = 10; const int c_l_b = 10; cout << "局部常量c_l_a的地址為: " << (int)&c_l_a << endl; cout << "局部常量c_l_b的地址為: " << (int)&c_l_b << endl; system("pause"); return 0; }
四、棧區——程序運行後
1、定義
由編譯器自動分配釋放,存放函數的參數值,局部變量等
註意 :不要返回局部變量的地址,棧區開辟的數據由編譯器自動釋放。
2、相關代碼
#include<iostream> #include<string> using namespace std; // 棧區註意事項——不要返回局部變量的地址 // 棧區的數據由編譯器管理開辟和釋放 int* func(int b) // 形參數據也會放在棧區 { b = 100; int a = 10; // 局部變量 存放在棧區,棧區的數據在函數執行完後自動釋放 return &a; // 返回局部變量的地址 } int main() { // 接收func函數的返回值 int* p = func(1); cout << *p << endl; // 第一次可以打印正確數字,是因為編譯器做瞭保留 cout << *p << endl; // 第二次就不保留瞭 system("pause"); return 0; }
五、堆區——運行後
1、定義
由程序員分配釋放,若程序員不釋放,程序結束時由操作系統回收
c++中主要利用new在堆區開辟內存
2、相關代碼和運行結果
#include<iostream> #include<string> using namespace std; int* func() { // 利用new關鍵字 可以將數據開辟到堆區 // 指針 本質也是局部變量,放在棧上,指針保存的數據是放在堆區 int* p = new int(10); return p; } int main() { // 在堆區開辟數據 int* p = func(); cout << *p << endl; cout << *p << endl; cout << *p << endl; cout << *p << endl; system("pause"); return 0; }
總結
本片文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- C++ 內存分區模型的使用(代碼區、全局區、棧區、堆區、new)
- C++ 命名空間 using聲明使用示例詳解
- C++深入淺出講解內存四區與new關鍵字的使用
- C++的數據類型你真的瞭解嗎
- C++的程序流程結構你瞭解多少