1.cpp
extern const int i; //const int i = 1;
const int i = 1; //extern const int i;
int main(){return 0;}
2.cpp
extern const int i = 2;
為什麼這樣不能通過鏈接,而如果按注釋裡的順序就能通過鏈接,這個怎麼解釋呢?
這個問題有幾個概念需要搞清楚。
1. const對象是文件局部變量。意味著,其他文件將不能Link到本文件的Const變量。
2. 如果在const前面加extern,意味著這個const對象可以被其他文件link到。
3. 在通過extern const變量進行獲取聲明而非初始化的時候,編譯器會首先選擇尋找這句extern之前有沒有該對象的初始化聲明。這是容易理解的,因為const的作用域本來就是文件作用域。如果在自己extern之前找不到(編譯器是自上而下編譯代碼,它並不知道自己之後是什麼),那麼去外部看有沒有其他使用extern方式初始化這個對象的地方。如果有,編譯通過。如果沒有會報link錯誤。
通過以上三點。我們來對你的代碼進行解讀。
你在1.cpp中如果先extern const int i,那麼根據上述第三點,它先找自己之前有沒有對i的初始化。很明顯沒有能夠找到。於是去文件外部尋找link的place holder,結果發現在2.cpp中果然有這麼一個定義。於是一個const i已經被找到並且已經被初始化。而此後第二句緊跟著就是一句對i的定義,因此此時一定會報link錯誤而不是編譯錯誤:fatal error LNK1169: one or more multiply defined symbols found。
那麼為什麼反過來就不會出錯呢?
很簡單,第一句定義了並且初始化了局部變量i,第二句extern這個變量,當extern的變量是const對象時,現在自己的文件裡面向上查找,如果找到,就不會再去其他地方link,因為const本來就是文件域。那麼自然不會存在剛才的link錯誤。你可以試一下運行結果,在main函數中將i打印出來,你會發現,i的值是1,而不是2.
這個問題可以發散得更多。如果概念清晰就不會害怕。
比如,我把const都去掉,會報什麼錯?等等。
希望我的回答能幫助你。