C++ 面向?qū)ο蟪绦蛟O(shè)計(jì)--內(nèi)存分區(qū)詳解
一、分區(qū)的意義
在講分區(qū)前,先談?wù)剝?nèi)存分區(qū)的意義,也就是為什么程序要進(jìn)行分區(qū)?
筆者認(rèn)為這是為了編程的靈活性,因?yàn)閷?nèi)存分區(qū)后,不同區(qū)域的內(nèi)存,相關(guān)的數(shù)據(jù)就有的不同的生命周期。以筆者之前的一篇算法復(fù)雜度的blog中提到棧幀空間為例,在此就是指棧區(qū),而棧區(qū)多指非main函數(shù)調(diào)用的內(nèi)存(相關(guān)參數(shù)等),當(dāng)非main函數(shù)調(diào)用結(jié)束后,這塊的內(nèi)存就會(huì)清空釋放。而這里的數(shù)據(jù)就可以和在main函數(shù)中的數(shù)據(jù)有不同的生命周期。
二、代碼區(qū)
1、定義
存放函數(shù)體內(nèi)的二進(jìn)制代碼,由操作系統(tǒng)進(jìn)行管理
注意:代碼區(qū)是在程序運(yùn)行前的內(nèi)存區(qū)域,除了代碼區(qū),運(yùn)行前還有全局區(qū)。代碼區(qū)存放的二進(jìn)制代碼其實(shí)就是編譯器(cpu)執(zhí)行的指令。
2、特點(diǎn)
1)代碼區(qū)是共享的,之所以共享是因?yàn)閷?duì)于被頻繁執(zhí)行的程序,只需要在內(nèi)存中存放一份代碼即可。避免內(nèi)存過(guò)多的浪費(fèi)。
2)代碼區(qū)是只讀的,原因是防止程序意外地修改了它的指令。
三、全局區(qū)
前面提到全局區(qū),也在程序執(zhí)行前。
1、定義
存放全局變量和靜態(tài)變量以及常量
2、特點(diǎn)
該區(qū)域的數(shù)據(jù)在程序結(jié)束后由操作系統(tǒng)釋放。
3、相關(guān)代碼
1)全局變量
#include<iostream> #include<string> using namespace std; // 全局變量 int g_a = 10; int g_b = 10; int main() { // 全局區(qū) // 全局變量、靜態(tài)變量、常量 // 創(chuàng)建普通局部變量 int a = 10; int b = 10; cout << "局部變量a的地址為: " << (int)&a << endl << "局部變量b的地址為: " << (int)&b << endl; cout << "全局變量g_a的地址為: " << (int)&g_a << endl; cout << "全局變量g_b的地址為: " << (int)&g_b << endl; system("pause"); return 0; }
程序執(zhí)行結(jié)果:
從結(jié)果看,局部變量和全局變量存放的地址顯然有很大的不同,而從a和b以及g_a和g_b的地址來(lái)看,全局變量和局部變量相鄰的變量的內(nèi)存地址是相近,從結(jié)果看是差了4,這是因?yàn)閱挝籭nt占4個(gè)字節(jié)。
2)靜態(tài)變量
// 靜態(tài)變量 在普通變量前面加static,屬于靜態(tài)變量 static int s_a = 10; static int s_b = 10; cout << "靜態(tài)變量s_a的地址為: " << (int)&s_a << endl; cout << "靜態(tài)變量s_b的地址為: " << (int)&s_b << endl;
將上述代碼加入到前面的main函數(shù)中,運(yùn)行得到如下結(jié)果
3)常量(不包含局部常量即const修飾的局部變量)
#include<iostream> #include<string> 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() { // 全局區(qū) // 全局變量、靜態(tài)變量、常量 // 創(chuàng)建普通局部變量 int a = 10; int b = 10; cout << "局部變量a的地址為: " << (int)&a << endl << "局部變量b的地址為: " << (int)&b << endl; cout << "全局變量g_a的地址為: " << (int)&g_a << endl; cout << "全局變量g_b的地址為: " << (int)&g_b << endl; // 靜態(tài)變量 在普通變量前面加static,屬于靜態(tài)變量 static int s_a = 10; static int s_b = 10; cout << "靜態(tài)變量s_a的地址為: " << (int)&s_a << endl; cout << "靜態(tài)變量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; // 局部常量 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; }
四、棧區(qū)——程序運(yùn)行后
1、定義
由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量等
注意 :不要返回局部變量的地址,棧區(qū)開(kāi)辟的數(shù)據(jù)由編譯器自動(dòng)釋放。
2、相關(guān)代碼
#include<iostream> #include<string> using namespace std; // 棧區(qū)注意事項(xiàng)——不要返回局部變量的地址 // 棧區(qū)的數(shù)據(jù)由編譯器管理開(kāi)辟和釋放 int* func(int b) // 形參數(shù)據(jù)也會(huì)放在棧區(qū) { b = 100; int a = 10; // 局部變量 存放在棧區(qū),棧區(qū)的數(shù)據(jù)在函數(shù)執(zhí)行完后自動(dòng)釋放 return &a; // 返回局部變量的地址 } int main() { // 接收f(shuō)unc函數(shù)的返回值 int* p = func(1); cout << *p << endl; // 第一次可以打印正確數(shù)字,是因?yàn)榫幾g器做了保留 cout << *p << endl; // 第二次就不保留了 system("pause"); return 0; }
五、堆區(qū)——運(yùn)行后
1、定義
由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)由操作系統(tǒng)回收
c++中主要利用new在堆區(qū)開(kāi)辟內(nèi)存
2、相關(guān)代碼和運(yùn)行結(jié)果
#include<iostream> #include<string> using namespace std; int* func() { // 利用new關(guān)鍵字 可以將數(shù)據(jù)開(kāi)辟到堆區(qū) // 指針 本質(zhì)也是局部變量,放在棧上,指針保存的數(shù)據(jù)是放在堆區(qū) int* p = new int(10); return p; } int main() { // 在堆區(qū)開(kāi)辟數(shù)據(jù) int* p = func(); cout << *p << endl; cout << *p << endl; cout << *p << endl; cout << *p << endl; system("pause"); return 0; }
總結(jié)
本片文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量(詳解)
下面小編就為大家?guī)?lái)一篇C++靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12Cocos2d-x Schedule定時(shí)器的使用實(shí)例
這篇文章主要介紹了Cocos2d-x Schedule定時(shí)器的使用實(shí)例,本文的講解內(nèi)容包含在代碼注釋中,需要的朋友可以參考下2014-09-09C語(yǔ)言使用結(jié)構(gòu)體實(shí)現(xiàn)簡(jiǎn)單通訊錄
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言使用結(jié)構(gòu)體實(shí)現(xiàn)簡(jiǎn)單通訊錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02C/C++調(diào)用Fortran的DLL的操作過(guò)程
這篇文章主要介紹了C/C++調(diào)用Fortran的DLL,本文以一個(gè)簡(jiǎn)單的加法器為例,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03c++動(dòng)態(tài)規(guī)劃經(jīng)典算法
動(dòng)態(tài)規(guī)劃算法通常用于求解具有某種最優(yōu)性質(zhì)的問(wèn)題。本文主要介紹了c++動(dòng)態(tài)規(guī)劃經(jīng)典算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08