c++內存分區模型

程序在運行的過程中是會被加載到內存中的,一個程序可能會執行可能會存在不同的功能塊,所以不同區域存放的數據,賦予不同的生命週期, 給我們更大的靈活編程

C++的程序會在內存中分爲四大塊:

  • 代碼區:存放函數體的二進制代碼,由操作系統進行管理的
  • 全局區:存放全局變量和靜態變量以及常量
  • 棧區:由編譯器自動分配釋放, 存放函數的參數值,局部變量等
  • 堆區:由程序員分配和釋放,若程序員不釋放,程序結束時由操作系統回收

代碼區

程序編譯後是一個二進制的文件,這個二進制的文件便會放在代碼區中。

代碼區是共享的,共享的目的是對於頻繁被執行的程序,只需要在內存中有一份代碼即可

代碼區是只讀的,使其只讀的原因是防止程序意外地修改了它的指令


全局區

  • 全局變量和靜態變量存放在此.
  • 全局區還包含了常量區, 字符串常量和其他常量也存放在此.
  • 該區域的數據在程序結束後由操作系統釋放.
  • C++中在程序運行前分爲全局區和代碼區
  • 代碼區特點是共享和只讀
  • 全局區中存放全局變量、靜態變量、常量
  • 常量區中存放 const修飾的全局常量 和 字符串常量,局部變量和局部常量是另外一個內存塊的棧的。

大概瞭解下是怎麼回事就行,可以定義不同的變量去觀察它們所在的地址塊是否連續在一起來判斷。


棧區

局部變量,局部常量都會分配到棧區中。

在函數中,實參傳遞給形參的過程是先在棧區爲形參開闢一塊內存塊,然後將實參的值寫入形參所在的內存塊。這就是爲什麼需要修改一個實參的數時需要傳遞指針或者引用(引用其實也是一個指針)。通過指針的地址再去改變相應的值。

一個函數執行完之後,都會把在這個函數中創建的形參(本質也是一個局部變量)或者局部變量進行退棧操作,也就是銷燬。銷燬後的值是沒有意義的。所以不能在一個函數中返回一個形參的地址,這是相當危險的操作。
如下程序:

int* test() {
	int i = 10; //在函數中創建的局部變量
	return &i; // 返回i的地址
}

int main() {
	int* p = test();
	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	return 0;
}

結果:

10
1515108752
1515108752

結果只有第一次正確,這是因爲編譯器暫時保留了一會,等到第二次去取值時就錯了。


堆區

那麼,上面的問題中,我們要怎麼在函數中創建變量,並且還不會在函數運行結束後就被銷燬呢?
解決方案其實也很優雅,就是另外開闢一個堆區,將用戶自己創建的變量都放到這個區中,然後用戶自行刪除或者等到程序結束時自動銷燬。
主要是用new來開闢的內存空間的。

int* test() {
	int* i = new int(10); // 在堆中開闢新的空間
	return i; // 返回i
}

int main() {
	int* p = test();
	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	return 0;
}

結果:

10
10
10

總結:

堆區數據由程序員管理開闢和釋放

堆區數據利用new關鍵字進行開闢內存


本文主要參考:黑馬程序員匠心之作|C++教程從0到1入門編程


更多精彩內容請關注我微信公衆號:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章