C++深入淺出講解內存四區與new關鍵字的使用

寫在前面

從本文開始我就要日常更新C++入門博文啦,從核心編程開始,之前的一些基礎我就不再從零整理瞭,隻有函數傳參、結構體、指針、數組等稍微難理解的知識在之前的博文寫的比較全面;因為競爭確實很大,其他人總結的也很好,要看更詳細的基礎就看本站的技能樹,非常全面;我寫博客的初衷一是可以記錄自己的學習,加以鞏固;二是給更多的人更容易的講解來快速入門C++,C/C++永不過時!!!

內存四區

下文有內存四區的詳細介紹及作用

內存四區的意義:不同區域存放的數據賦予不同的生命周期,讓我們的編程方式更靈活。

程序運行前

在程序編譯後,生成瞭可執行程序.exe,未執行程序前分為兩個區域為代碼區和全局區

代碼區

作用:

存放CPU執行的機器指令(二進制代碼,由操作系統進行管理)

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

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

全局區

全局變量和靜態常量存放在此

全局區還包含瞭常量區,字符串常量和其他常量也存放在此

該區域的數據在程序結束後由操作系統釋放

代碼示例:

#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;
	cout << "局部變量a的地址為:" << (int)& a << endl;
	cout << "局部變量b的地址為:" << (int)& b << endl;
	int c_l_a = 10;
	int c_l_b = 10;
	cout << "局部常量c_l_a的地址為:" << (int)&c_l_a << endl;
	cout << "局部變量c_l_b的地址為:" << (int)&c_l_b << endl;
	cout << "全局變量g_a的地址為:" << (int)&g_a << endl;
	cout << "全局變量g_b的地址為:" << (int)&g_b << endl;
	//靜態變量
	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;
}

各變量地址的關系:

從運行效果可以清楚的看到帶全局的變量地址所占空間相近,而局部的地址相差就比較遠瞭,看下我做的圖示總結:

程序運行後

棧區

由編譯器自動分配釋放,存放函數的參數值,局部變量等

註意事項:不要返回局部變量的地址,棧區開辟的數據由編譯器自動釋放

#include<iostream>
using namespace std;
int* func1(int b)//返回值類型為 int *,所以return一個地址才合法
{//形參數據也會開辟到棧區
	b = 100;
	int a = 10;//局部變量,存放在棧區,棧區的數據在函數執行完成後自動釋放
	return &a;//返回局部變量的地址
}
int main()
{
	//接受func1函數的返回值
	int* p = func1(10);
	cout << *p << endl;//第一次數據正常,因為編譯器會自動保留
	cout << *p << endl;//第二次往後是隨機數,該地址被釋放
	cout << *p << endl;
}

tips:這裡輸出隻有一個10,剩下輸出結果無法猜測,因為返回的地址已經被編譯器釋放掉

堆區

由程序員分配釋放,若程序員不釋放,程序結束時由操作系統回收

在C++中主要利用new在棧區開辟內存

示例:

int * func()
{
	//利用new 關鍵字把棧開辟到堆區
	//指針 *p實質上也是棧區數據,指針保存的數據放到堆區
	int* p = new int (10);
	return p;
}
int main()
{
	int* a = func();
	cout << *a << endl;//無論輸出多少次,都能輸出a的值
	cout << *a << endl;
	cout << *a << endl;
}

這裡不同於棧區的時,無論輸出多少次*a,都是結果十,下面來張圖助理解:

主函數中用*a作為*p的返回值,a的地址為0x0011,保存的數據為10,這是數據保存在堆中,除非程序結束,該地址都不會被釋放。

new關鍵字

new的基本語法

開辟:

數據類型 + 指針變量 = new +相同數據類型 +(賦值)

這樣可在堆區開辟數據,作為棧區函數返回值也不會被編譯器自動釋放

刪除:

delete 變量地址

堆區數據由管理員開辟或釋放,如果想要釋放數據就利用delete關鍵字

利用new開辟數組

示例:int* Array = new int[n]; 和基本語法相比就是()變成瞭[],並且裡面可以存放常量或者變量,當我們想控制數組長度的時候,這也是自定義的一種方法。讓 n 等於10,那麼數組Array[]的長度為十,我們可以用隨機數來給數組賦值。釋放數組也是利用delete關鍵字,例如 delete[] Array; 刪除數組加[]放在數組名前。

例如:

void test02(int *Array)
{
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 10; i++)
	{
		Array[i] = rand() % 20 + 1;
	}
	for (int i = 0; i < 10; i++)
	{
		cout << Array[i] << "  ";
	}
}
int main()
{
    int *Array = new int [10];
    test02(Array);
}

附帶個運行圖:

到此這篇關於C++深入淺出講解內存四區與new關鍵字的使用的文章就介紹到這瞭,更多相關C++內存四區內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: