在C中,const不是常量,只能說是一個不能改變的變量(注意是變量),C編譯器不能把const當作當作一個編譯期間的常量,由於他在內存中有分配,C編譯器不知道他在編譯期間的值。因此不能做爲數組定義時的下標,由於它必須爲常量。c++
在C中,const int a;是能夠的,由於這只是聲明一個變量,告訴編譯器,我這裏是聲明,指明在別的地方有內存分配。但在C++中這樣寫是不正確的,C++中const默認是內部連接,C中默認是外部連接,爲了起到和c語言同樣的效果,C++須要將const修飾爲extern,由於extern優先級高於const,因此變量會被變爲extern外部連接,起到和C語言同樣的效果。[ (1) 內鏈接:編譯器只對正被編譯的文件建立存儲空間,別的文件可使用相同的表示符或全局變量.C/C++中內鏈接使用static關鍵字指定.(2) 外鏈接:全部被編譯過的文件建立一片單獨存儲空間.一旦空間被建立,鏈接器必須解決對這片存儲空間的引用.全局變量和函數使用外部鏈接.經過extern關鍵字聲明,能夠從其餘文件訪問相應的變量和函數. ] 通俗的講:在c++ 中const 對象默認爲文件的局部變量。與其餘變量不一樣,除非特別說明,在全局做用域聲明的 const 變量是定義該對象的文件的局部變量。此變量只存在於那個文件中,不能被其餘文件訪問。經過指定 const 變動爲 extern,就能夠在整個程序中訪問 const 對象。數組
C++中是否爲const分配內存空間要看具體狀況,若是被聲明爲extern或者取const變量地址,就須要爲const變量分配空間。函數
當在本身的文件中使用const的時候,C++不會爲const常量分配空間,由於這是一種優化措施,沒有必要浪費空間去存儲一個常量,此時const int a=5 就至關於#define a 5,當在其餘文件使用的時,須要分配內存,一樣在程序內部引用的時候,也須要分配內存,由於這二者都是採用尋址的技術去使用的,不分配內存就沒有地址。C++中定義常量的時候再也不採用define,由於define只作簡單的宏替換,並不提供類型檢查。優化
C++中用const定義了一個常量後,不會分配一個空間給它,而是將其寫入符號表(symbol table),這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。可是const定義的常量本質上也是一個變量,是變量就會有地址,那麼何時會分配內存?spa
1 int main() 2 { 3 const int a = 2; 4 int* p = (int*)(&a); 5 *p = 30; 6 cout << &a << endl; 7 cout << p << endl; 8 cout << a << endl; 9 cout << *p << endl; 10 return 0; 11 } 12 13 /*運行結果: 14 ----------- 15 010FF958 16 010FF958 17 2 18 30 19 ----------- 20 */
經過 int*p = (int*)(&a);這種方法,能夠直接修改const常量對應的內存空間中的值,但修改不會影響到常量自己的值,由於用到a的時候,編譯器根本不會去進行內存空間的讀取。這就是C++的常量摺疊constant folding,即將const常量放在符號表中,而並不給其分配內存。編譯器直接進行替換優化。除非須要用到a的存儲空間的時候,編譯器無可奈何纔會分配一個空間給a,但以後a的值仍舊從符號表中讀取,無論a的存儲空間中的值如何變化,都不會對常量a產生影響。code
可是在C語言中卻不是這樣,C沒有constant folding的概念,用const定義一個常量的時候,編譯器會直接開闢一個內存空間存放該常量。不會進行優化。一樣的例子在C下面會產生不一樣的結果:對象
1 int main() 2 { 3 const int a = 2; 4 int* p = (int*)(&a); 5 *p = 30; 6 printf("%x\n",&a); 7 printf("%x\n",p); 8 printf("%i\n",a); 9 printf("%i\n",*p); 10 return 0; 11 } 12 13 /*運行結果 14 ------------ 15 61fe14 16 61fe14 17 30 18 30 19 ------------*/
C中,一個被const定義爲常量的值,卻能被修改,並且編譯器不報任何錯誤 。進一步深刻可發現,對於以上兩個例子來講,a都是定義在某個函數以內的(好比main()函數),不論是C仍是C++,本質上都只是將其當成一個普通的局部變量來對待,都只是在棧上分配空間。因此const根本就不能起到阻止修改其內存空間的做用,一個合法的強制類型轉換就能夠輕鬆搞定。C++比C好的地方就在於使用了constant folding的機制,使得常量的值跟對應的內存空間無關,從而保護了該常量值。blog
1 const int a = 3; 2 int arr[a];
但C會報錯: error: variably modified 'arr' at file scope, 緣由在於GCC認爲a只是一個普通的全局變量,而變量是不能用來指定數組的長度的,這是針對全局數組而言。但若是是局部的數組的話,就算是int a = 3; int arr[a];這種都是能夠的,若在C和C++中若是咱們仍然用int *p = (int*)(&a);這種方法來修改它內存中的值,編譯時不會報錯,可是運行時會報錯誤,由於a是放在只讀的全局數據區中,修改該區中的數據會引起段錯誤。內存