目錄:
- 單獨編譯
- 存儲持續性、作用域和連結性
一、單獨編譯
- 頭檔案常包含的内容:函數原型、使用#define或const定義的符号常量、結構聲明、類聲明、模闆聲明、内聯聲明。
若頭檔案中檔案名包含在尖括号中,則C++編譯器将在存儲标準頭檔案的主機系統的檔案系統中查找;若檔案包含在雙引号中,則編譯器将首先查找目前的工作目錄或源代碼目錄。
2. 在同一個檔案中隻能将同一個頭檔案包含一次。避免方法:基于預處理器編譯指令#ifndef與#endif(編譯器将檢視這之間的内容,讓它忽略除第一次包含之外的所有内容)
二、存儲持續性、作用域和連結性
- 自動存儲持續性:在函數定義中聲明的變量(包括函數參數)的存儲持續性為自動的。程式開始執行其所屬的函數或代碼塊時被建立,在執行完函數或代碼塊時其記憶體被釋放。
- 靜态存儲持續性:在函數定義外定義的變量和使用關鍵字static定義的變量的存儲持續性都為靜态。(在程式運作過程中都存在)
- 線程存儲持續性:多核處理器,讓程式能将計算放在可并行處理的不同線程中,若變量是使用關鍵字thread_local聲明的,則其生命周期與所屬線程一樣長。
- 動态存儲持續性:用new運算符配置設定的記憶體将一直存在,直到使用delete運算符将其釋放或程式結束為止。這種記憶體的存儲持續性為動态,有時也被稱為自由存儲或堆。
五種變量存儲方式:
存儲描述 | 持續性 | 作用域 | 連結性 | 如何聲明 |
自動 | 自動 | 代碼塊 | 無 | 在代碼塊中 |
寄存器 | 自動 | 代碼塊 | 無 | 代碼塊中,關鍵字register |
靜态,無連結性 | 靜态 | 代碼塊 | 無 | 代碼塊中,關鍵字static |
靜态,外部連結性 | 靜态 | 檔案 | 外部 | 不在任何函數内 |
靜态,内部連結性 | 靜态 | 檔案 | 内部 | 不在任何函數内,使用static |
1. 作用域描述了名稱在檔案(翻譯單元)的多大範圍可見。作用域為全局(檔案作用域)的變量在定義位置到檔案結尾之間都可用;自動變量的作用域為局部;在函數原型作用域中使用的名稱隻在包含參數清單的括号内可用;在類中聲明的成員的作用域為整個類;在名稱空間中聲明的變量的作用域為整個名稱空間;C++函數的作用域可以是整個類或整個名稱空間(包括全局的),但不能是局部的(不能在代碼塊内定義函數)。
連結性描述了名稱如何在不同單元間共享;連結性為外部的名稱可在檔案間共享,連結性為内部的名稱隻能由一個檔案中的函數共享
2. 自動存儲持續性
預設情況下,在函數中聲明的函數參數和變量的存儲持續性為自動,作用域為局部,沒有連結性。代碼塊中定義的變量的存在時間和作用域将被限制在該代碼塊内。
可以使用任何在聲明時其值為已知的表達式來初始化自動變量。
程式使用兩個指針來跟蹤棧,一個指針指向棧底—棧的開始位置,另一個指針指向堆頂—下一個可用記憶體單元,棧是後進先出的,即最後加入到棧中的變量首先被彈出。
關鍵字register建議編譯器使用CPU寄存器來存儲自動變量。
3. 靜态持續變量
C++為靜态存儲持續性變量提供了3種連結性:外部連結性(可在其它檔案中通路)、内部連結性(隻能在目前檔案中通路)、無連結性(隻能在目前函數和代碼塊中通路)
所有的靜态持續變量都有以下初始化特征:未被初始化的靜态變量的所有位都被設定成0. 這種變量被稱為零初始化的,也可對靜态變量進行常量表達式初始化和動态初始化。
4. 靜态持續性、外部連結性
連結性為外部的變量通常簡稱為外部變量,它們的存儲持續性為靜态,作用域為整個檔案。
C++提供兩種變量聲明:一是定義聲明(給變量配置設定記憶體空間),另一種是引用聲明(引用已有變量,使用關鍵字extern且不進行初始化)。
作用域解析運算符(::)放在變量名前表示使用變量的全局版本。程式越能避免對資料進行不必要的通路,就越能保持資料的完整性。通常情況下應使用局部變量。
5. 靜态持續性、内部連結性
将static限定符用于作用域為整個檔案的變量時,該變量的連結性将為内部的。連結性為内部的變量隻能在其所屬的檔案中使用;連結性為外部的正常外部變量可以在其他檔案中使用。
如檔案中定義了一個靜态外部變量,其名稱與另一個檔案中聲明的正常外部變量相同,則在該檔案中,靜态變量将隐藏正常外部變量。
在多檔案程式中,可以在一個檔案(且隻能在一個檔案)中定義一個外部變量。使用該變量的其他檔案必須使用extern聲明它。
6. 靜态存儲持續性、無連結性
将static限定符用于在代碼塊中定義的變量。其存儲持續性為靜态的。若初始化了靜态局部變量,則程式隻在啟動時進行一次初始化,之後再調用函數時将不會像自動變量那樣再次被初始化。
7. 說明符和限定符
a.存儲說明符:auto(自動類型推斷)、register(寄存器存儲,C++11中顯式的指出變量是自動的)、static、extern(引用聲明)、thread_local(指出變量的持續性與其所屬線程的持續性相同)、mutable(根據const解釋)
b.CV-限定符:const、volatile(即使程式代碼沒有對記憶體單元進行修改,其值也可能發生改變,該關鍵字的作用是改善編譯器的優化能力)
mutable:可用它指出,即使結構(或類)變量為const,其某個成員也可被修改。
c.預設情況下全局變量的連結性為外部的,但const全局變量的連結性為内部的。即在C++看來,全局const定義就像使用了static說明符一樣,這還意味着每個檔案都有自己的一組常量,而不是所有檔案共享一組常量。
d.鑒于單個const在多個檔案間共享,是以隻有一個檔案可對其進行初始化。
8. 函數和連結性
所有的函數的存儲持續性都自動為靜态的。即在整個程式執行期間一直存在。預設情況下,函數的連結性為外部的,即可在檔案間共享(可以在函數原型中使用extern)。使用static将函數的連結性設定為内部的,使之隻能在一個檔案中使用,必須同時在原型和函數定義中使用static。C++要求同一個函數的所有内聯定義都必須相同,對于每個非内聯函數,程式隻能包含一個定義。
9. 語言連結性
連結程式要求每個不同的函數都有不同的符号名。C++編譯器執行名稱矯正或名稱修飾,為重載函數生成不同的符号名稱。