總結C++中關於extern關鍵字的用法。
1.變量的生明和定義中
C++語言支持分離式編譯機制,該機制允許將程序分割為若干個文件,每個文件可被獨立編譯。為了將程序分為許多文件,則需要在文件中共享代碼,例如一個文件的代碼可能需要另一個文件中中定義的變量。
為了支持分離式編譯,C++允許將聲明和定義分離開來。變量的聲明規定了變量的類型和名字,即使一個名字為程序所知,一個文件如果想使用別處定義的名字則必須包含對那個名字的聲明。定義則負責創建與名字關聯的實體,定義還申請存儲空間。
如果想聲明一個變量而非定義它,就在變量名前添加extern關鍵字,而且不要顯式地初始化變量:
extern int i; //聲明i而非定義
int j; //聲明並定義i
但我們也可以給由extern關鍵字標記的變量賦一個初始值,但這樣就不是一個聲明了,而是一個定義:
extern int v = 2;
int v = 2; //這兩個語句效果完全一樣,都是v的定義
注意: 變量能且只能被定義一次,但是可以被聲明多次。
2.在多個文件中共享const對象
默認情況下,一個const對象僅在本文件內有效,如果多個文件中出現了同名的const變量時,其實等同於在不同的文件中分別定義了獨立的變量。
某些時候有這樣一種const變量,它的初始值不是一個常量表達式,但又確實有必要在文件間共享。這種情況下,我們不希望編譯器為每個文件分別生成獨立的變量。我們想讓這類const對象像其他非常量對象一樣工作,也就是說,只在一個文件中定義const,而在其他多個文件中聲明並使用它。
方法是對於const變量不管是聲明還是定義都添加extern關鍵字,這樣只需要定義一次就可以了:
//file1.cpp定義並初始化和一個常量,該常量能被其他文件訪問
extern const int bufferSize = function();
//file1.h頭文件
extern const int bufferSize; //與file1.cpp中定義的是同一個
file1.h頭文件中的聲明也由extern做了限定,其作用是指明bufferSize並非本文件獨有,它的定義將出現在別處。
3.模板的控制實例化
當兩個或者多個獨立編譯的源文件中使用了相同的模板並且提供了相同的模板參數時,每個文件中都會有該模板的一個實例。
在大系統中,在多個文件中實例化相同的模板的額外開銷可能非常嚴重,在C++11新標准中,我們可以通過顯式實例化來避免這種開銷。一個顯式實例化具有如下形式:
extern template declaration; //實例化聲明
template declaration; //實例化定義
declaration是一個類或函數的聲明,其中所有的模板參數都已經被替換成為模板實參。例如:
extern template class vec<string>; //聲明
template int sum(const int, const int); //定義
當編譯器遇到extern模板聲明時,它不會在本文件中生成實例化代碼,將一個實例化聲明為extern就表示承諾在程序的其他位置有該實例化的一個非extern定義。對於一個給定的實例化版本,可能有多個extern聲明,但必須只有一個定義。
由於編譯器在使用一個模板時自動對其實例化,因此extern聲明必須出現在任何使用此實例化吧版本的代碼之前。
由於以上討論可知:extern一般是使用在多文件之間需要共享某些代碼時。