C++核心程式設計 1 程式的記憶體模型
1、記憶體分割槽模型
C++程式在執行時,將記憶體大方向劃分為4個區域
程式碼區:存放函式體的二進位制程式碼,由作業系統進行管理(寫的所有程式碼都在程式碼區)
全域性區:存放全域性變數、靜態變數以及常量
棧 區:由編譯器自動分配釋放,存放函式的引數值,區域性變數等
堆 區:由程式設計師分配和釋放,若程式設計師不釋放,程式結束時由作業系統回收
記憶體四區的意義:不同區域的資料,賦予不同的生命週期,給我們更大的靈活程式設計
程式執行前:
在程式編譯後,生成了exe可執行程式,未執行該程式前分為兩個區域
程式碼區:
存放CPU執行的機器指令
程式碼區是共享的,共享的目的是對於頻繁被執行的程式,只需要在記憶體中有一份程式碼即可
程式碼區是隻讀的,使其只讀的原因是防止程式意外地修改了它的指令
全域性區:
全域性變數(main函式外面)和靜態變數(在普通變數前加static)存放於此
全域性區還包含了常量區,字串常量 ("hello world") 和其他常量(const修飾的全域性變數)也存放於此
該區域的資料在程式結束後由作業系統釋放
總結:
C++中在程式執行前分為全域性區和程式碼區
程式碼區特點是共享和只讀
全域性區中存放全域性變數、靜態變數、常量
常量區中存放const修飾的全域性變數和字串常量
程式執行後:
棧 區:
由編譯器自動分配釋放,存放函式的引數值,區域性變數等
注意:不要返回區域性變數的地址,棧區開闢的資料由編譯器自動釋放
#include<iostream> using namespace std; //棧區資料注意事項 --- 不要返回區域性變數的地址 //棧區的資料由編譯器管理開闢和釋放 int * func(int b) //形引數據也會放在棧區 {
b = 100;
cout << b << endl; int a = 10; //區域性變數 存放棧區,棧區的資料在函式執行完後自動釋放 return &a; //返回區域性變數的地址 } int main() {//接收函式的返回值 int * p = func(1); cout << *p << endl; //第一次可以打印出正確的資料 10 ,是因為編譯器防止使用者是誤操作而做了一次保留 cout << *p << endl; //第二次這個資料就不再保留 打印出來的是亂碼 因為區域性變數a的記憶體已經被釋放 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; cout << *p << endl; system("pause"); return 0; }
列印結果:
new操作符
C++中利用new操作符在堆區開闢資料
堆區開闢的資料,由程式設計師手動開闢,手動釋放,釋放操作符delete
語法:new資料型別
利用new建立的資料,會返回該資料對應的型別的指標
例項:1、基本語法
#include<iostream> using namespace std; int * func() { //在堆區建立整型資料 //new返回的是 該資料型別的指標 int * p = new int (10); return p; } void test1() //new的基本語法 { int * p = func(); cout << *p << endl; cout << *p << endl; cout << *p << endl; //堆區資料由程式設計師管理開闢、釋放,若想釋放 利用關鍵字delete delete p; cout << *p << endl; //記憶體已經被釋放,再次訪問就是非法操作,會報錯 } int main() { //int * p = func(); //接收函式的返回值 test1(); system("pause"); return 0; }
列印結果:因為deletep 後,p已被釋放,故第四次打印出錯。
2、在堆區new陣列
#include<iostream> using namespace std; //2、在堆區利用new開闢陣列 void test2() { //建立10個 整型資料的陣列,在堆區 int * arr = new int[10]; //10代表陣列有10個元素 for (int i = 0; i < 10; i++) { arr[i] = i + 100; //給10個元素賦值 100~109 } for (int i = 0; i < 10; i++) { cout << arr[i] << endl; } //釋放堆區陣列 //釋放陣列的時候要加[]才可以 delete[] arr; } int main() { test2(); system("pause"); return 0; }
列印結果: