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