C++學習心得第二期 記憶體四區+new+引用+函式高階

CodeCong發表於2020-09-28

一、記憶體四區

1.記憶體分割槽模型

C++程式在執行時,將記憶體大方向劃分為4個區域
程式碼區:存放函式體的二進位制程式碼,由作業系統進行管理的
全域性區:存放全域性變數和靜態變數以及常量
棧區:由編譯器自動分配釋放, 存放函式的引數值,區域性變數等
堆區:由程式設計師分配和釋放,若程式設計師不釋放,程式結束時由作業系統回收

2.程式執行前全域性區和程式碼區

​ 在程式編譯後,生成了exe可執行程式,未執行該程式前分為兩個區域
​ 程式碼區:
​ 存放 CPU 執行的機器指令
​ 程式碼區是共享的,共享的目的是對於頻繁被執行的程式,只需要在記憶體中有一份程式碼即可
​ 程式碼區是隻讀的,使其只讀的原因是防止程式意外地修改了它的指令
​ 全域性區:
​ 全域性變數和靜態變數存放在此.
​ 全域性區還包含了常量區, 字串常量和其他常量也存放在此.
該區域的資料在程式結束後由作業系統釋放.

C++中在程式執行前分為全域性區和程式碼區
程式碼區特點是共享和只讀
全域性區中存放全域性變數、靜態變數、常量
常量區中存放 const修飾的全域性常量 和 字串常量

#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,屬於靜態變數
	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修飾的全域性變數

	cout << "全域性常量c_g_a的地址" << (int)&c_g_a << endl;
	cout << "全域性常量c_g_b的地址" << (int)&c_g_b << 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_a << endl;


	system("pause");
	return 0;
}

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

3.程式執行後 棧區和堆區

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

#include<iostream>
using namespace std;

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

int* xingcan(int a)
{
	a = 100;
	return &a;
}

int main()
{
	//不能返回區域性變數
	int* a = fun();
	cout << *a<< endl;  //第一可以列印是因為列印正確的數字,是因為編譯器做了正確的保留
	cout << *a << endl; //第二次這個資料不再儲存了
	//不能返回函式中的形式引數
	int test = 10;
	int* xc = xingcan(test);

	//讀不出正確的資料
	cout << *xc << endl;
	cout << *xc << endl;

	system("pause");
	return 0;
}

由程式設計師分配釋放,若程式設計師不釋放,程式結束時由作業系統回收
在C++中主要利用new在堆區開闢記憶體
堆區資料由程式設計師管理開闢和釋放
堆區資料利用new關鍵字進行開闢記憶體

#include<iostream>
using namespace std;

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

int main()
{
	//在堆區開闢資料
	int *p = fun();

	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;

	system("pause");
	return 0;
}

在這裡插入圖片描述

在這裡插入圖片描述

二、new關鍵字

​ C++中利用new操作符在堆區開闢資料
​ 堆區開闢的資料,由程式設計師手動開闢,手動釋放,釋放利用操作符 delete
​ 語法: new 資料型別
​ 利用new建立的資料,會返回該資料對應的型別的指標

1.基本語法

#include<iostream>
using namespace std;

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

int main()
{
	//在堆區開闢資料
	int *p = fun();

	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;

	//釋放堆區資料
	delete p;
	cout << *p << endl; //程式報錯
	system("pause");
	return 0;
}

2.開闢陣列

#include<iostream>
using namespace std;
int main()
{
	int *arr = new int[10];

for (int i = 0; i < 10; i++)
{
	arr[i] = i + 100;
}
for (int i = 0; i < 10; i++)
{
	cout << arr[i] << endl;
}
//釋放陣列 delete 後加 []
delete [] arr;

system("pause");

return 0;
}

二、引用

相關文章