1. 程式人生 > 其它 >C++核心程式設計---1.程式的記憶體模型【P84~P88】

C++核心程式設計---1.程式的記憶體模型【P84~P88】

技術標籤:C++學習

C++核心程式設計---1.程式的記憶體模型【P84~P88】

【C++核心程式設計階段主要針對C++面向物件程式設計技術做詳細講解,探討C++中的核心和精髓】

C++程式在執行時,將記憶體大方向劃分為4個區域

  • 程式碼區:存放函式體的二進位制程式碼,由作業系統進行管理的
  • 全域性區:存放全域性變數和靜態變數以及常量
  • 棧區:由編譯器自動分配釋放,存放函式的引數值,區域性變數等
  • 堆區:由程式設計師分配和釋放,若程式設計師不釋放,程式結束時由作業系統回收

記憶體四區意義:
不同區域存放的資料,賦予不同的生命週期,給我們更大的靈活程式設計

程式執行前:
程式碼區

  • 存放CPU執行的機器指令
  • 程式碼區是共享的,共享的目的是對於頻繁被執行的程式,只需要在記憶體中有一份程式碼即可
  • 程式碼區是只讀的,使其只讀的原因是防止程式意外地修改了它的指令

全域性區

  • 全域性變數和靜態變數存放在此
  • 全域性區還包含了常量區,字串常量和其他常量也存放在此
  • 該區域的資料在程式結束後由作業系統釋放
# include<iostream>
using namespace std;

//建立全域性變數
int g_a = 10;
int g_b = 10;

//const修飾的全域性變數,全域性常量
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; cout << "區域性變數b的地址為: " << (int)&b << endl; cout << "全域性變數g_a的地址為: " << (int)&g_a << endl; cout << "全域性變數g_b的地址為: "
<< (int)&g_b << endl; //建立靜態變數 static int s_a; static int s_b; cout << "靜態變數s_a的地址為: " << (int)&s_a << endl; cout << "靜態變數s_b的地址為: " << (int)&s_b << endl; //常量 //字串常量 cout << "字串常量的地址為: " << (int)&"hello world" << endl; //const修飾的變數 //const修飾的全域性變數 cout << "全域性常量 c_g_a 的地址為: " << (int)&c_g_a << endl; cout << "全域性常量 c_g_b 的地址為: " << (int)&c_g_a << endl; //const修飾的區域性變數 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; }

通過對比驗證可以發現:

  • 全域性區中存放全域性常量
  • 常量區中存放 const 修飾的全域性常量 和 字串常量

程式執行後:
棧區

  • 由編譯器自動分配釋放,存放函式的引數值,區域性變數等
  • 注意事項:不要返回區域性變數的地址,棧區開闢的資料由編譯器自動釋放
# include<iostream>

int * func()
{
	int a = 10;//區域性變數,存放在棧區,棧區的資料在函式執行完後自動釋放
	return &a;//返回區域性變數的地址
}

int main()
{
	int * p = func();

	std::cout << *p << std::endl;//第一次可以列印正確數字,是因為編譯器給做了保留
	std::cout << *p << std::endl;//第二次這個數字就不再保留了

	system("pause");
	return 0;
}

堆區

  • 由程式設計師分配釋放,若程式設計師不釋放,程式結束時由操怍系統回收
  • 在C++中主要利用new在堆區開闢記憶體
# include<iostream>

using namespace std;

int * func()
{
	//利用new關鍵字  可以將資料開闢到堆區
	//這裡指標本質上也是區域性變數,放在棧上,但是指標儲存的資料是放在堆區的
	int * p = new int(10);
	return p;
}

int main()
{
	int * p = func();
	cout << *p << endl;

	system("pause");
	return 0;
}

new操作符
在這裡插入圖片描述