有些被稱為存儲說明符(storage class specifier)或cv-限定符(cv-qualifier)的C++關鍵字提供了一些有關存儲的信息。下面是存儲所說明符:
* auto (在C++11中不再是說明符);
* register;
* static;
* extern;
* thread_local(C++11新增的);
* mutable。
在同一個聲明中不能使用多個說明符,但thread_local除外,它可與static或extern結合使用。
在C++11之前,可以在聲明中使用關鍵字auto指出變量為自動變量;但在C++11中,auto用於自動類型推斷。
在C++11之前,register用於在聲明中指示寄存器存儲,而在C++11中,它指示顯式地指出變量是自動的。
關鍵字static被用在作用於為整個文件的聲明中時,表示內部鏈接性;被用於局部聲明中,表示局部變量的存儲持續性為靜態的。
關鍵字extern表明是引用聲明,即聲明引用在其他地方定義的變量。
關鍵字thread_local指出變量的持續性與其所屬線程的持續性相同。thread_local變量之於線程,猶如常規靜態變量之於整個程序。
1.cv-限定符
下面就是cv限定符:
* const;
* volatile
關鍵字const表明,內存被初始化后,程序便不能再對它進行修改。
關鍵字volatile表明,即使程序代碼沒有對內存單元進行修改,其值也可能發生變化。例如,可以將指針指向某個硬件位置,其中包含了來自串行端口的時間和信息。在這種情況下,硬件(而不是程序)可能修改其中的內容。或者兩個程序可能互相影響,共享數據。該關鍵字的作用是為了改善編譯器的優化能力。例如,假設編譯器發現,程序在幾條語句中連續使用了某個變量的值,則編譯器可能不是讓程序查找這個值兩次,而是將這個值緩存到寄存器中。這種優化假設變量的值在着來那個詞使用之間不會變化。如果不將變量聲明為volatile,則編譯器將進行這種優化:將變量聲明為volatile,相當於告訴編譯器,不要進行這種優化。
2.mutable
現在回到mutable。可以用它來指出,即使結構(或類)變量為const,其某個成員也可以被修改。例如,下面的代碼:
struct data
{
char name[30];
mutable int accesses;
...
};
const data veep = {"Alaybourne Clodde", 0, ... };
strcpy(veep.name, "moonlit"); // not allowed
veep.accesses ++; // allowed
veep的const限定符禁止程序修改veep的成員,但access成員的mutable說明符使得access不受這種限制。
3.const
在C++(但不是C語言)中,const限定符對默認存儲類型稍有影響。在默認情況下全局變量的鏈接型為外部的,但const全局變量的鏈接型為內部的。也就是說,在C++看來,全局const(如下述代碼段所示)就像使用了static說明符一樣。
const int fingers = 10; // same as static const int fingers = 10;
int main(void)
{
...
C++修改了常量類型的規則,讓程序員更輕松。例如,假設將一組常量放在頭文件中,並在同一個程序的多個文件中使用該頭文件。那么,預處理其將頭文件的內容包含到每個源文件中后,所有的源文件都將包含類似下面這樣的定義:
const int fingers = 10;
const char * warning = "Wak!";
如果全局const聲明的鏈接像常規變量那樣是外部的,則根據單定義規則,這將出錯。也就是說,只能有一個文件可以包含前面的聲明,而其他文件必須使用extern關鍵字來提供引用聲明。另外,只有未使用extern關鍵字的聲明才能進行初始化。
// extern would be required if const had external linkage
extern const int fingers; // can't be initialized
extern const char * warning;
因此,需要為某個文件使用一組定義,而其他文件使用另一組聲明。
如果出於某種原因,程序員希望某個常量的鏈接性為外部的,則可以使用extern關鍵字來覆蓋默認的內部鏈接性:
extern const int states = 50; // definition with external linkage
在這種情況下,必須在所有使用該常量的文件中使用extern關鍵字來聲明它。這與常規外部變量不同,定義常規外部變量時,不必使用extern關鍵字,但在使用該變量的其他文件中必須使用extern。然而,請記住,鑒於單個const在多個文件之間共享,因此只有一個文件可對其進行初始化。
在函數或代碼塊中聲明const時,其作用域為代碼塊,即僅當程序執行代代碼塊中的代碼時,該常量才是可用的。這意味着在函數或代碼塊中創建常量時,不必擔心其名稱與其他地方定義的常量發生沖突。