介紹
在計算機中,標識符是程式中變數、類型、函式和標號的名稱。標識符作用域是指標識符綁定的實體在一個程式中有效的部分或表示著一個標識符(identifier)的作用範圍。一般而言,標識符不同,標識符作用域是不同的,同一個標識符在不同命名空間的作用域是不同的,因為一個標識符可在多個命名空間中定義,但它在不同命名空間中的含義是互不相干的。理解標識符作用域,對分析整個程式功能和對程式進行最佳化是十分重要的。
標識符
標識符是一個字元序列,用來標識變數、函式、數據類型等。任何程式都離不開標識符,也就是說,不可能有沒有標識符的C++程式。在程式2-1中,include、void、main、int、i、cin、cout等都是標識符。
標識符可以由大寫字母、小寫字母、下劃線(_)和數字0~9組成,但必須是以大寫字母、小寫字母或下劃線(_)開頭。在C++語言程式中,大寫字母和小寫字母不能混用,比如Name和name就代表兩個不同的標識符。
標識符的命名規則:
1. 所有標識符必須由一個字母(a~z或A~Z)或下劃線(_)開頭;
2. 標識符的其它部分可以用字母、下劃線或數字(0~9)組成;
3. 大小寫字母表示不同意義, 即代表不同的標識符,如前面的cout和Cout;
在定義標識符時,雖然語法上允許用下劃線開頭,但是,我們最好避免定義用下劃線開頭的標識符,因為編譯器常常定義一些下劃線開頭的標識符。
C++沒有限制一個標識符中字元的個數,但是,大多數的編譯器都會有限制。不過,我們在定義標識符時,通常並不用擔心標識符中字元數會不會超過編譯器的限制,因為編譯器限制的數字很大(例如255)。
一個寫得好的程式,標識符應該儘量有意義。 比如表示年可以用year,表示長度可以用length,表示累加和可以用sum等,這樣的標識符本身就增加了程式的可讀性,使程式更加清晰易懂。
C++語言的標識符經常用在以下情況中:
1. 標識對象或變數的名字
2. 類、結構和聯合的成員
3. 函式或類的成員函式
4. 自定義類型名
5. 標識宏的名字
6. 宏的參數
作用域
概述
在電腦程式設計中, 作用域(scope,或譯作有效範圍)是名字(name)與實體(entity)的綁定(binding)保持有效的那部分電腦程式。不同的程式語言可能有不同的 作用域和名字解析。而同一語言內也可能存在多種 作用域,隨實體的類型變化而不同。 作用域類別影響變數的綁定方式,根據語言使用 靜態作用域還是 動態作用域變數的取值可能會有不同的結果。
•包含標識符的宣告或定義;
•包含語句和/或表達式,定義或部分關於可運行的算法;
•嵌套嵌套或被嵌套嵌套。
名字空間是一種作用域,使用作用域的封裝性質去邏輯上組群起關相的眾識別子於單一識別子之下。因此, 作用域可以影響這些內容的名字解析。
程式設計師常會縮進他們的原始碼中的 作用域,改善可讀性。
靜態作用域與動態作用域
靜態作用域又叫做詞法作用域,採用詞法作用域的變數叫 詞法變數。詞法變數有一個在編譯時靜態確定的作用域。詞法變數的作用域可以是一個函式或一段代碼,該變數在這段代碼區域內可見(visibility);在這段區域以外該變數不可見(或無法訪問)。詞法作用域裡,取變數的值時,會檢查函式定義時的文本環境,捕捉函式定義時對該變數的綁定。
大多數現在程式設計語言都是採用靜態作用域規則,如C/C++、C#、Python、Java、JavaScript……
相反,採用 動態作用域的變數叫做 動態變數。只要程式正在執行定義了動態變數的代碼段,那么在這段時間內,該變數一直存在;代碼段執行結束,該變數便消失。這意味著如果有個函式f,裡面調用了函式g,那么在執行g的時候,f里的所有局部變數都會被g訪問到。而在靜態作用域的情況下,g不能訪問f的變數。動態作用域裡,取變數的值時,會由內向外逐層檢查函式的調用鏈,並列印第一次遇到的那個綁定的值。顯然,最外層的綁定即是全局狀態下的那個值。
採用動態作用域的語言有Pascal、Emacs Lisp、Common Lisp(兼有靜態作用域)、Perl(兼有靜態作用域)。C/C++是靜態作用域語言,但在宏中用到的名字,也是動態作用域。
類型
函式作用域
函式作用域(function scope),只適用標籤(label)的名字。標籤名字可以在它所出現的函式中的任何位置被goto語句使用。也就是說,在函式內部,可以先通過goto語句使用一個標籤名字,之後在該函式內部才有該標籤名字的定義。
函式原型作用域
函式原型作用域(function prototype scope)是指,函式原型中聲明的名字只在該原型結束前可見,在原型結束處即為作用域結束之處。 例:
全局作用域
全局命名空間作用域(global namespace scope),也稱作全局作用域(global scope)是指編譯單元的最外部的聲明區域中聲明的名字的作用域。 這些名字在程式的各個編譯單元之間均可見。全局名字是連結器需要識別的名字。一般說來,全局名字對應的實體在程式中應僅有一份,而不同編譯單元都可以通過同一名字綁定到該實體上。
典型的具有全局作用域的名字,包括:全局變數、全局函式等。
C++規定,可以通過::來限定一個名字為全局作用域中的名字。這也是“全局命名空間”稱謂的來源。例如:
枚舉作用域
枚舉作用域(enumeration scope)是指枚舉類型的成員(enumerator)的名字的作用域,起自其聲明之處,終至枚舉定義結束之處。
C語言規定,枚舉類型的成員(enumerator)的可見範圍被提升至該枚舉類型所在的作用域內。這被認為有可能污染了外部的作用域。為此,C++11引入了枚舉類(enum class)解決此問題。