如下參考了網上的一些資料並經過程序驗證。c++
注意,如下狀況都是用gcc和g++編譯器獲得的結果,用vs編譯器又會有所不一樣。數組
如下說下c和c++中const定義的常量的一些區別:函數
c++中用const定義了一個常量後,不會分配一個空間給它,而是將其寫入符號表(symbol table),這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。可是const定義的常量本質上也是一個變量,是變量就會有地址,那麼何時會分配內存?看看下面的代碼:優化
int main(){ const int a = 2; int* p = (int*)(&a); *p = 30; cout<<&a<<endl; cout<<p<<endl; cout<<a<<endl; cout<<*p<<endl; }
結果:spa
咱們看到,經過 int*p = (int*)(&a);這種方法,能夠直接修改const常量對應的內存空間中的值,可是這種修改不會影響到常量自己的值,由於用到a的時候,編譯器根本不會去進行內存空間的讀取。這就是c++的常量摺疊(constant folding),即將const常量放在符號表中,而並不給其分配內存。編譯器直接進行替換優化。除非須要用到a的存儲空間的時候,編譯器無可奈何纔會分配一個空間給a,但以後a的值仍舊從符號表中讀取,無論a的存儲空間中的值如何變化,都不會對常量a產生影響。code
可是在c中卻不是這樣.c沒有constant folding的概念,用constant定義一個常量的時候,編譯器會直接開闢一個內存空間存放該常量。不會進行優化。一樣的例子在c下面會產生不一樣的結果:blog
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 }
結果:內存
咱們看到,在c裏面,一個被const定義爲常量的值,冠冕堂皇地被修改了,並且編譯器沒有報任何錯誤 !編譯器
若是咱們進一步深刻能夠發現,對於以上兩個例子來講,a都是定義在某個函數以內的(好比main()函數),無論是c仍是c++,本質上都只是將其當成一個普通的局部變量來對待,都只是在棧上分配空間。因此const根本就不能起到阻止修改其內存空間的做用,一個合法的強制類型轉換就能夠輕鬆搞定。c++比c好的地方就在於使用了constant folding的機制,使得常量的值跟對應的內存空間無關,從而保護了該常量值。it
以上的例子是針對局部的const常量而言,對全局的const變量,c++仍舊採用constant folding策略,故如下代碼是行得通的:
//global variable const int a = 3; int arr[a];
可是c會報錯: error: variably modified 'arr' at file scope, 緣由在於gcc認爲a只是一個普通的全局變量,而變量是不能用來指定數組的長度的。固然,這是針對全局數組而言,若是是局部的數組的話,就算是int a = 3; int arr[a];這種都是能夠的,由於c裏面還有一種叫變長數組的東西(我暈~,貌似由於二者的實現機制不同,這個要再看看)
另外,對於a,在c和c++中若是咱們仍然用int *p = (int*)(&a);這種方法來修改它內存中的值,編譯時不會報錯,可是運行時會報段錯誤,由於a是放在只讀的全局數據區中,修改該區中的數據會引起段錯誤。
在vs編譯器下:
1.不支持變長數組,一個變量除非被聲明爲const,不然不能用來聲明數組的長度。
2.const變量,無論是全局的仍是局部,都是放在只讀數據區,因此沒法用前面的方法來修改內存空間裏面的值,編譯時就會報錯。