詳解C++中的自動存儲
C++有3種管理數(shù)據(jù)內(nèi)存的方式即自動存儲(棧存儲)、靜態(tài)存儲和動態(tài)存儲(堆存儲)。在不同的方式下,內(nèi)存的分配形式和存在時間的長短都不同。
下面對自動存儲進(jìn)行說明。
自動存儲(棧存儲)
對于函數(shù)的形參、內(nèi)部聲明的變量及結(jié)構(gòu)變量等,編譯器將在函數(shù)執(zhí)行時為形參自動分配存儲空間,在執(zhí)行到變量和結(jié)構(gòu)變量等的聲明語句時為其自動分配存儲空間,因此稱其為自動變量(Automatic Variable),有的教科書也稱其為局部變量,在函數(shù)執(zhí)行完畢返回時,這些變量將被撤銷,對應(yīng)的內(nèi)存空間將被釋放。
事實(shí)上,自動變量的生存期只局限于它所在的代碼塊。所謂代碼塊,是包含在花括號對中的一段代碼,函數(shù)只是代碼塊的一種,比較下面兩段代碼。
代碼段1
int add(int m,int n) { //z的生存期包括整個函數(shù) int z=m+n; return z; }
代碼段2
int add(int m,int n) { if(m!=0) { //z的生存期包括在這個代碼塊中 int z=m+n; } return z;//錯誤 }
在代碼段1中,當(dāng)函數(shù)返回時,變量z被撤銷,對應(yīng)內(nèi)存空間被釋放,但在代碼段2中,在if代碼塊中聲明的變量z,其生存期僅限于if結(jié)構(gòu)的兩個花括號之間,當(dāng)程序執(zhí)行到if結(jié)構(gòu)的后花括號時,變量z已被撤銷,其對應(yīng)的內(nèi)存空間被釋放,此時,再執(zhí)行“return z;”語句便會出錯。
注意
理解代碼塊的含義十分重要,花括號不是判斷代碼塊的唯一標(biāo)準(zhǔn),把代碼段2中if結(jié)構(gòu)的花括號去掉,代碼仍然是錯誤的,將“return z;”放在if結(jié)構(gòu)中是正確的用法。
自動變量的生存期是局部的,這一特性使得程序員可以在不同的塊內(nèi)使用相同的變量名,用不著為使用不同的變量名絞盡腦汁。
1.什么是“?!?br />
棧(Stack)是一塊存儲區(qū),而且是C++程序使用最頻繁的存儲區(qū),其存儲機(jī)理為“FILO”,即先進(jìn)后出(First In,Last Out)??梢詫⑵湎胂蟪梢粋€裝盤子的桶,最早放入的盤子在桶的底部,最晚放入的盤子在最頂部,取盤子時必須先從后放進(jìn)去的盤子開始取,這就是所謂的先進(jìn)后出原則。當(dāng)一個代碼塊(包括函數(shù),視為一種特殊的代碼塊)聲明一個自動變量時,系統(tǒng)便為其在棧中開辟內(nèi)存空間(常稱“壓入”push),該代碼塊結(jié)束后便將自動變量撤銷,釋放內(nèi)存空間(常稱“彈出”pop)。
注意
采用“棧”這種機(jī)制,C++程序能有效地節(jié)省所用內(nèi)存空間。
2.auto關(guān)鍵字
auto是C++提供的存儲類聲明符,用于聲明自動變量,除了auto聲明符外,C++還提供了另外3個存儲類聲明符,分別是register(寄存器存儲)、extern(外部存儲)和static(靜態(tài)存儲)。在聲明創(chuàng)建變量時,存儲類聲明符應(yīng)放在數(shù)據(jù)類型聲明符之前,如下所示。
存儲類聲明符 數(shù)據(jù)類型 變量名[=初始化表達(dá)式]
其中,初始化表達(dá)式是可選的,如下列代碼聲明創(chuàng)建了int型自動變量A,其只在函數(shù)demo()執(zhí)行期間存在,demo()函數(shù)執(zhí)行完畢后,變量A被撤銷,對應(yīng)內(nèi)存被釋放。
void demo() { …… auto int A; …… }
在前面給出的示例代碼在聲明自動變量時并沒有加auto修飾符,實(shí)際上,auto常??梢阅J(rèn),凡是在函數(shù)內(nèi)部(不論是main()函數(shù)還是其他函數(shù))的,沒有用其他顯式的存儲類型聲明符,編譯器都認(rèn)為是auto型自動變量。
3.register關(guān)鍵字
除了auto外,還可以通過存儲類聲明符register來聲明自動變量,與auto唯一的不同在于:關(guān)鍵字register通知編譯器,用戶希望通過CPU寄存器,而不是“?!眮硖幚砟硞€變量,從而可以在一定程度上加快該變量的訪問速度。
提示
一般來說,CPU對寄存器的訪問要快過對內(nèi)存的訪問。
用register聲明的變量常稱為寄存器變量,舉例來說,下列代碼聲明了int型寄存器變量sum,并將其初始化為9,如下所示。
register int sum=9;
需要注意的是,即使用register聲明了某個變量,編譯器也不一定會滿足它的要求。因?yàn)?,CPU寄存器可能被占用或者無法存儲指定類型的數(shù)據(jù)等,而且,現(xiàn)在的編譯器一般可以自動決定應(yīng)把哪些變量放在CPU寄存器中,因此,在C++程序中,register關(guān)鍵字很少使用。
使用register關(guān)鍵字會帶來一定的負(fù)面效果,不管是否能滿足要求,編譯器認(rèn)為register型自動變量是存儲在CPU寄存器中的,而寄存器是沒有內(nèi)存地址的,所以,不能對register型自動變量進(jìn)行取地址操作,下列代碼是錯誤的。
void demo() { …… register int sum=0; int*pSum=∑ …… }
注意
事實(shí)上,用auto和register聲明的變量除了存儲位置不同(一個是“?!保硪粋€可能是“?!币部赡苁荂PU寄存器)外,并無其他差異,我們可以將其統(tǒng)稱為自動變量來考慮。
4.自動變量的初始化
可以在聲明自動變量時對其進(jìn)行初始化,也可以使用任何具有確定值的表達(dá)式為自動變量賦值,下列語句都是合法的(假定n為int型自動變量)。
n=2; n=5*m;//m的值確定 n=add(4,6);
需要特別注意的是,如果沒有在自動變量聲明的同時對其初始化,其初始值是隨機(jī)、不可預(yù)料的,為避免隨機(jī)的初始值給程序帶來麻煩,推薦在聲明自動變量的同時對其顯式初始化。
以上就是詳解C++中的自動存儲的詳細(xì)內(nèi)容,更多關(guān)于C++ 自動存儲的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Qt重寫QStackedWidget模擬實(shí)現(xiàn)home界面滑動效果
這篇文章主要為大家詳細(xì)介紹了Qt如何通過重寫QStackedWidget模擬實(shí)現(xiàn)home界面滑動效果,文中的實(shí)現(xiàn)過程講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-11-11使用pthread庫實(shí)現(xiàn)openssl多線程ssl服務(wù)端和客戶端
使用pthread庫實(shí)現(xiàn)openssl多線程ssl服務(wù)端和客戶端,大家參考使用吧2014-01-01從頭學(xué)習(xí)C語言之switch語句和分支嵌套
這篇文章主要為大家詳細(xì)介紹了C語言之switch語句和分支嵌套,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01C語言實(shí)例實(shí)現(xiàn)二叉搜索樹詳解
二叉搜索樹是以一棵二叉樹來組織的。每個節(jié)點(diǎn)是一個對象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點(diǎn)的左孩子,right指向該節(jié)點(diǎn)的右孩子,p指向該節(jié)點(diǎn)的父節(jié)點(diǎn),key是它的值2022-05-05C語言中strspn()函數(shù)和strcspn()函數(shù)的對比使用
這篇文章主要介紹了C語言中strspn()函數(shù)和strcspn()函數(shù)的對比使用,strspn是計(jì)算屬于字符串的字符數(shù)而strcspn則是判斷不屬于,需要的朋友可以參考下2015-08-08VSCode插件開發(fā)全攻略之package.json詳解
這篇文章主要介紹了VSCode插件開發(fā)全攻略之package.json的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05VS Code C/C++環(huán)境配置教程(無法打開源文件“xxxxxx.h”或者檢測到 #include 錯誤,請更新in
這篇文章主要介紹了VS Code C/C++環(huán)境配置教程(無法打開源文件“xxxxxx.h” 或者 檢測到 #include 錯誤。請更新includePath) (POSIX API),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08