初識(shí)C++內(nèi)存分區(qū)模型
在了解內(nèi)存分區(qū)之前拴袭,我們先來(lái)聊一聊為什么要進(jìn)行內(nèi)存分區(qū)授艰。在進(jìn)行了內(nèi)存分區(qū)之后隘道,在不同的區(qū)域存放的數(shù)據(jù)们妥,會(huì)有不同的生命周期猜扮,從而會(huì)讓程序員的編程變得更加靈活。
我們這次討論的內(nèi)存模型是將內(nèi)存劃分為四部分的版本监婶,也是筆者在和黑馬學(xué)習(xí)過(guò)程中學(xué)習(xí)到的版本旅赢。
而C++在程序運(yùn)行的過(guò)程中,將內(nèi)存分為四個(gè)區(qū)域:
代碼區(qū)
存放函數(shù)的二進(jìn)制代碼压储,即CPU執(zhí)行的機(jī)器指令鲜漩,由操作系統(tǒng)進(jìn)行管理。全局區(qū)
存放全局變量集惋、靜態(tài)變量(static孕似,分為全局與局部靜態(tài)變量)和部分常量。棧區(qū)
由編譯器自動(dòng)分配和釋放刮刑,存放函數(shù)的參數(shù)值喉祭、局部變量养渴、局部常量等。堆區(qū)
由程序員進(jìn)行分配和釋放泛烙,而如果程序員不釋放理卑,則在程序結(jié)束運(yùn)行時(shí),由操作系統(tǒng)來(lái)進(jìn)行回收蔽氨。
程序運(yùn)行前
程序編譯后藐唠,會(huì)生成可執(zhí)行程序,而在該程序未執(zhí)行之前鹉究,內(nèi)存分為代碼區(qū)和全局區(qū)兩個(gè)區(qū)域宇立。
代碼區(qū)
存放函數(shù)的二進(jìn)制代碼,即CPU執(zhí)行的機(jī)器指令自赔,由操作系統(tǒng)進(jìn)行管理妈嘹。
代碼區(qū)的特性是共享與只讀:
- 共享:對(duì)于被頻繁執(zhí)行的程序,在內(nèi)存中只需要保存一份代碼即可绍妨。
- 只讀:防止程序被意外修改润脸。
全局區(qū)
存放全局變量、靜態(tài)變量(static)和部分常量他去。
其中部分常量為常量區(qū)毙驯,即字符串常量和全局常量( const 關(guān)鍵字修飾的全局常量);不包括局部常量灾测。
程序運(yùn)行后
棧區(qū)
由編譯器自動(dòng)分配和釋放尔苦,存放函數(shù)的參數(shù)值、局部變量行施、局部常量等允坚。
堆區(qū)
由程序員進(jìn)行分配和釋放,而如果程序員不釋放蛾号,則在程序結(jié)束運(yùn)行時(shí)稠项,由操作系統(tǒng)來(lái)進(jìn)行回收。
主要利用 new 在堆區(qū)開(kāi)辟內(nèi)存鲜结,由 delete 進(jìn)行釋放展运。
ps:利用 new 常見(jiàn)的數(shù)據(jù),返回的是該數(shù)據(jù)對(duì)應(yīng)類型的指針精刷。
內(nèi)存分區(qū)代碼示例
#include <iostream>
using namespace std;
//全局變量 全局區(qū)
int global_a=10;
int global_b=20;
//全局常量 全局區(qū)
const int global_const_a=10;
const int global_const_b=20;
//全局靜態(tài)變量 全局區(qū)
static int static_global_a=10;
static int static_global_b=20;
//形參 棧區(qū)
void func(int a){
//局部變量 棧區(qū)
int b=20;
cout<<"函數(shù)func()的形參 a 的地址為:"<< &a <<endl;
cout<<"函數(shù)func()的局部變量 b 的地址為:"<< &b <<endl<<endl;
}
int main() {
cout<<"棧區(qū)"<<endl;
//局部變量 棧區(qū)
int a = 10;
int b = 20;
cout<<"局部變量 a 的地址為:"<< &a <<endl;
cout<<"局部變量 b 的地址為:"<< &b <<endl;
//局部常量 棧區(qū)
const int const_a=10;
const int const_b=10;
cout<<"局部常量 const_a 的地址為:"<< &const_a <<endl;
cout<<"局部常量 const_b 的地址為:"<< &const_b <<endl;
//形參 棧區(qū)
func(a);
cout<<"全局區(qū)"<<endl;
cout<<"全局變量 global_a 的地址為:"<< &global_a <<endl;
cout<<"全局變量 global_b 的地址為:"<< &global_b <<endl;
cout<<"全局常量 global_const_a 的地址為:"<< &global_const_a <<endl;
cout<<"全局常量 global_const_a 的地址為:"<< &global_const_b <<endl;
cout<<"全局靜態(tài)變量 static_global_a 的地址為:"<< &static_global_a <<endl;
cout<<"全局靜態(tài)變量 static_global_b 的地址為:"<< &static_global_b <<endl;
//局部靜態(tài)變量 全局區(qū)
static int Static_a=10;
static int Static_b=20;
cout<<"局部靜態(tài)變量 Static_a 的地址為:"<< &Static_a <<endl;
cout<<"局部靜態(tài)變量 Static_b 的地址為:"<< &Static_b <<endl;
//字符串常量 全局區(qū)
cout<<"字符串常量的地址為:"<< &"hello world s1" <<endl;
cout<<"字符串常量的地址為:"<< &"hello world s2" <<endl<<endl;
cout<<"堆區(qū)"<<endl;
//new 堆區(qū)
int* new_a=new int(10);
int* new_b=new int(20);
cout<<"堆區(qū)變量 new_a 的地址為:"<< new_a <<endl;
cout<<"堆區(qū)變量 new_a 的地址為:"<< new_b <<endl<<endl;
return 0;
}
運(yùn)行結(jié)果分析如下: