天天看點

const在C和C++中的差別

  在C中,const不是常量,隻能說是一個不能改變的變量(注意是變量),C編譯器不能把const看成一個編譯期間的常量,因為他在記憶體中有配置設定,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定義的常量本質上也是一個變量,是變量就會有位址,那麼什麼時候會配置設定記憶體?

int main()
{
    const int a = 2;
    int* p = (int*)(&a);
    *p = 30;
    cout << &a << endl;
    cout << p << endl;
    cout << a << endl;
    cout << *p << endl;
    return 0;
}

/*運作結果:
-----------
010FF958
010FF958
2
30
-----------
*/      

  通過 intp = (int)(&a);這種方法,可以直接修改const常量對應的記憶體空間中的值,但修改不會影響到常量本身的值,因為用到a的時候,編譯器根本不會去進行記憶體空間的讀取。這就是C++的常量折疊constant folding,即将const常量放在符号表中,而并不給其配置設定記憶體。編譯器直接進行替換優化。除非需要用到a的存儲空間的時候,編譯器迫不得已才會配置設定一個空間給a,但之後a的值仍舊從符号表中讀取,不管a的存儲空間中的值如何變化,都不會對常量a産生影響。

  但是在C語言中卻不是這樣,C沒有constant folding的概念,用const定義一個常量的時候,編譯器會直接開辟一個記憶體空間存放該常量。不會進行優化。同樣的例子在C下面會産生不同的結果:

int main()
{
    const int a  = 2;
    int* p = (int*)(&a);
    *p = 30;
    printf("%x\n",&a);
    printf("%x\n",p);
    printf("%i\n",a);
    printf("%i\n",*p);
    return 0;
}

/*運作結果
------------
61fe14
61fe14
30
30
------------*/      

  C中,一個被const定義為常量的值,卻能被修改,而且編譯器不報任何錯誤 。進一步深入可發現,對于以上兩個例子來說,a都是定義在某個函數之内的(比如main()函數),不管是C還是C++,本質上都隻是将其當成一個普通的局部變量來對待,都隻是在棧上配置設定空間。是以const根本就不能起到阻止修改其記憶體空間的作用,一個合法的強制類型轉換就可以輕松搞定。C++比C好的地方就在于使用了constant folding的機制,使得常量的值跟對應的記憶體空間無關,進而保護了該常量值。

const int a = 3;
int arr[a];      

繼續閱讀