詳解C++作用域與生命周期
Pascal之父Nicklaus Wirth曾經(jīng)提出一個(gè)公式,展示出了程序的本質(zhì):程序=算法+數(shù)據(jù)結(jié)構(gòu)。后人又給出一個(gè)公式與之遙相呼應(yīng):軟件=程序+文檔。這兩個(gè)公式可以簡(jiǎn)潔明了的為我們展示程序和軟件的組成。
程序的運(yùn)行過(guò)程可以理解為算法對(duì)數(shù)據(jù)的加工過(guò)程,程序的運(yùn)行的結(jié)果,就是算法加工數(shù)據(jù)產(chǎn)生的結(jié)果數(shù)據(jù)。算法描述的是對(duì)數(shù)據(jù)加工的步驟,對(duì)應(yīng)于程序中的函數(shù)。數(shù)據(jù)結(jié)構(gòu)描述的是數(shù)據(jù)在計(jì)算機(jī)中的組織結(jié)構(gòu),對(duì)應(yīng)于程序中的數(shù)據(jù)類型。程序中數(shù)據(jù)對(duì)應(yīng)的就是無(wú)處不在變量。對(duì)于我們編程人員,面對(duì)的無(wú)非就是函數(shù),數(shù)據(jù)類型和變量。因此,C++談及作用域與生命周期針對(duì)的就是這三大程序的組成要素:函數(shù)、數(shù)據(jù)類型和變量。下面將一一講述。
1.作用域與生命周期的區(qū)別
作用域與生命周期是兩個(gè)完全不同的概念。在英文中,作用域用“scope”表示,生命周期則用“duration”表示。作用域是一個(gè)靜態(tài)概念,只在編譯源程序的時(shí)候用到。一個(gè)標(biāo)識(shí)符的作用域指在源文件中該標(biāo)識(shí)符能夠獨(dú)立地合法出現(xiàn)的區(qū)域。生命周期則是一個(gè)運(yùn)行時(shí)(Runtime)概念,它是指一個(gè)變量在整個(gè)程序從載入到結(jié)束運(yùn)行的過(guò)程中存在的時(shí)間周期。由于函數(shù)和數(shù)據(jù)類型是靜態(tài)的概念,它們沒(méi)有生命周期的說(shuō)法,它們從編譯、程序的運(yùn)行到結(jié)束整個(gè)過(guò)程是一直存在的。
C++中作用域的級(jí)別由高到低,主要有文件域(全局作用域)、名字空間域、類域、函數(shù)作用域和代碼塊作用域,其中函數(shù)作用域和代碼塊作用域又統(tǒng)稱為局部域。
2.函數(shù)的作用域
函數(shù)分為類的成員函數(shù)和全局函數(shù)。
類的成員函數(shù):
- 作用域:類域。
- 生命周期:無(wú)(程序運(yùn)行期一直存在)。
- 引用方法:其他文件中要使用點(diǎn)操作符(.)或指針操作符(->)或作用域運(yùn)算符(::)來(lái)引用。
- 內(nèi)存分布:代碼區(qū)。
- 注意:類成員函數(shù)可以定義在類體內(nèi),即定義在頭文件,當(dāng)類被不同源文件包含時(shí)不會(huì)報(bào)重定義的錯(cuò)誤,因?yàn)轭愺w內(nèi)實(shí)現(xiàn)的函數(shù)具有inline特性。
舉例如下:
//main.cpp class test { private: int i; public: void show() { cout<<"i:"<<i<<endl; } }; int main(int argc,char* argv[]) { test t; t.show() }
全局函數(shù):
- 作用域:文件域(全局作用域)。
- 生命周期:無(wú)(程序運(yùn)行期一直存在)。
- 引用方法:其他文件中要先進(jìn)行函數(shù)原型聲明,再使用。
- 內(nèi)存分布:代碼段。
- 注意:如果在兩個(gè)源文件中定義了同名的全局函數(shù),連接時(shí)會(huì)出現(xiàn)重定義錯(cuò)誤。
舉例如下:
//function.cpp void printHello() { cout<<"hello world"<<endl; } //main.cpp void printHello(); int main(int argc,char* argv[]) { printHello(); }
3.數(shù)據(jù)類型的作用域
C++中的數(shù)據(jù)類型分為基本數(shù)據(jù)類型和非基本數(shù)據(jù)類型,非基本數(shù)據(jù)類型中又分為復(fù)合數(shù)據(jù)類型和構(gòu)造數(shù)據(jù)類型。關(guān)于C++中的數(shù)據(jù)類型,詳見(jiàn)本人另一篇blog: C++數(shù)據(jù)類型。
基本數(shù)據(jù)類型:
基本數(shù)據(jù)類型包括整型(int)、實(shí)型(float和double)、字符型(char)、布爾型(bool)和無(wú)值型(void)。
- 作用域:文件域(全局作用域)。
- 生命周期:無(wú)(程序運(yùn)行期一直存在)。
- 引用方法:無(wú)需申明,直接使用。
- 內(nèi)存分布:代碼段。
復(fù)合數(shù)據(jù)類型:
復(fù)合數(shù)據(jù)類型包括:數(shù)組(type[])、指針(type*)、引用(type&)、枚舉(enum)。
如果復(fù)合數(shù)據(jù)類型是構(gòu)造數(shù)據(jù)類型參與的復(fù)合,其作用域與構(gòu)造數(shù)據(jù)類型一致。enum枚舉類型的作用域與構(gòu)造類型相同。
構(gòu)造數(shù)據(jù)類型:
- 作用域:類型定義所在的域,其他文件不可見(jiàn)。
- 生命周期:無(wú)(程序運(yùn)行期一直存在)。
- 引用方法:其他文件中要先進(jìn)行定義,再通過(guò)作用域運(yùn)算符進(jìn)行使用。
- 內(nèi)存分布:代碼區(qū)。
- 注意:只要文件不互相包含,如果在兩個(gè)源文件中定義了同名的構(gòu)造,不會(huì)出現(xiàn)重定義錯(cuò)誤,因?yàn)閿?shù)據(jù)類型不具有外部連接性。
舉例如下:
//main.cpp namespace dd { class test { private: int i; public: void show() { cout<<"i:"<<i<<endl; } }; } using namespace dd;//引用命名空間域中的構(gòu)造類型test,否則無(wú)法使用 int main(int argc,char* argv[]) { test t; t.show(); }
4.變量的作用域與生命周期
我們面對(duì)的變量主要分為全局變量、全局靜態(tài)變量、局部變量和局部靜態(tài)變量。下面一一講述他們的作用域與生命周期。
全局變量:
- 作用域:全局作用域(全局變量只需在一個(gè)源文件中定義,就可以作用于所有的源文件);
- 生命周期:程序運(yùn)行期一直存在;
- 引用方法:其他文件中要使用必須用extern 關(guān)鍵字聲明要引用的全局變量。;
- 內(nèi)存分布:全局/靜態(tài)存儲(chǔ)區(qū);
- 注意:如果在兩個(gè)文件中都定義了相同名字的全局變量,連接出錯(cuò):變量重定義。
舉例如下:
//define.cpp int g_iValue = 1; //main.cpp extern int g_iValue; int main() { cout << g_iValue; return 0; }
全局靜態(tài)變量:
- 作用域:文件作用域(只在被定義的文件中可見(jiàn));
- 生命周期:程序運(yùn)行期一直存在;
- 內(nèi)存分布:全局/靜態(tài)存儲(chǔ)區(qū);
- 定義方法:static關(guān)鍵字,const 關(guān)鍵字;
- 注意:只要文件不互相包含,在兩個(gè)不同的文件中是可以定義完全相同的兩個(gè)靜態(tài)變量的,它們是兩個(gè)完全不同的變量。
舉例如下:
//define.cpp const int iValue=8; //main.cpp int iValue; static const int iValue_2; static int iValue_3; int main(int argc,char* argv[]) { cout<<"iValue:"<<iValue<<endl; return 0; }
局部變量:
- 作用域:局部作用域(只在局部作用域中可見(jiàn),如函數(shù)域,代碼塊域);
- 生命周期:程序運(yùn)行出局部作用域即被銷毀;
- 內(nèi)存分布:棧區(qū);
- 注意:auto指示符標(biāo)示。
舉例如下:
void print() { int a=0; cout<<a<<endl; }
局部靜態(tài)變量:
- 作用域:局部作用域(只在局部作用域中可見(jiàn));
- 生命周期:程序運(yùn)行期一直存在;
- 內(nèi)存分布:全局靜態(tài)存儲(chǔ)區(qū);
- 定義方法:局部作用域用中用static定義;
- 注意:只被初始化一次,多線程中需加鎖保護(hù)。
舉例如下:
void function() { static int iREFCounter = 0; }
5.擴(kuò)展知識(shí)點(diǎn)
5.1變量存儲(chǔ)類型說(shuō)明符
C語(yǔ)言中提供了四種存儲(chǔ)類型說(shuō)明符auto,register,extern和static,四種存儲(chǔ)類型有兩種存儲(chǔ)期:自動(dòng)存儲(chǔ)期和靜態(tài)存儲(chǔ)期。其中auto和register對(duì)應(yīng)自動(dòng)存儲(chǔ)期,被修飾的變量在進(jìn)入聲明該變量的程序塊時(shí)被建立,它在該程序塊活動(dòng)時(shí)存在,退出該程序塊時(shí)撤銷。靜態(tài)存儲(chǔ)期的變量從程序載入運(yùn)行到程序結(jié)束一直存在。
5.2static使用建議
(1)若全局變量?jī)H在單個(gè)C文件中訪問(wèn),則可以將這個(gè)變量修改為靜態(tài)全局變量,以降低模塊間的耦合度;
(2)若全局變量?jī)H由單個(gè)函數(shù)訪問(wèn),則可以將這個(gè)變量改為該函數(shù)的靜態(tài)局部變量,以降低模塊間的耦合度;
(3)設(shè)計(jì)和使用訪問(wèn)動(dòng)態(tài)全局變量、靜態(tài)全局變量、靜態(tài)局部變量的函數(shù)時(shí),需要考慮重入問(wèn)題,因?yàn)樗麄兌挤旁陟o態(tài)數(shù)據(jù)存儲(chǔ)區(qū),可被其他函數(shù)共享;
(4)如果我們需要一個(gè)可重入的函數(shù),那么我們一定要避免函數(shù)中使用static變量。這樣的函數(shù)被稱為帶“內(nèi)部存儲(chǔ)器”功能的函數(shù);
(5)函數(shù)中必須要使用static變量情況:比如當(dāng)某函數(shù)的返回值為指針類型時(shí),則必須是static的局部變量的地址作為返回值,若為auto類型,則返回為野指針。
以上就是詳解C++作用域與生命周期的詳細(xì)內(nèi)容,更多關(guān)于C++作用域與生命周期的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++零基礎(chǔ)精通數(shù)據(jù)結(jié)構(gòu)之帶頭雙向循環(huán)鏈表
帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單2022-03-03Linux?C/C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具
網(wǎng)絡(luò)流量分析的原理基于對(duì)數(shù)據(jù)包的捕獲、解析和統(tǒng)計(jì)分析,通過(guò)對(duì)網(wǎng)絡(luò)流量的細(xì)致觀察和分析,幫助管理員了解和優(yōu)化網(wǎng)絡(luò)的性能,本文將通過(guò)C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具,有需要的可以參考下2023-10-10詳解C語(yǔ)言gets()函數(shù)與它的替代者fgets()函數(shù)
這篇文章主要介紹了詳解C語(yǔ)言gets()函數(shù)與它的替代者fgets()函數(shù)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10學(xué)習(xí)二維動(dòng)態(tài)數(shù)組指針做矩陣運(yùn)算的方法
這片文章介紹了如何利用二維動(dòng)態(tài)數(shù)組指針做矩陣運(yùn)算,需要的朋友可以參考下2015-07-07M1 Macbook vscode C++ debug調(diào)試實(shí)現(xiàn)
本文主要介紹了M1 Macbook vscode C++ debug調(diào)試,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08數(shù)組名不等于指針?sizeof()函數(shù)求數(shù)組大小錯(cuò)誤問(wèn)題及解決
這篇文章主要介紹了數(shù)組名不等于指針?sizeof()函數(shù)求數(shù)組大小錯(cuò)誤問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11Ubuntu20.04安裝使用jsoncpp、json-c庫(kù)的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Ubuntu20.04安裝使用jsoncpp、json-c庫(kù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作就有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-04-04