概覽C++之const

來源:互聯網
上載者:User

標籤:資料   整數   常指標   保留   特性   post   解構函式   指標   center   

 1、C語言中const與 C++中的const

void main(){  const int a = 10;  int *p = (int*)&a;  *p = 20;  printf("%d", a);}

     比較上述代碼在C中和C++中執行結果:C:列印20;C++:列印0。

     由此可見,C語言中的const是個“冒牌貨”,C++中 的const是一個真正的常量。

     原因:C語言直接為a分配了記憶體。

C語言中的const變數是僅僅讀變數,有自己的儲存空間。而C++編譯器對const的處理是:當碰見常量聲明時,在“符號表”(C++編譯器專門設定的)中放入常量,在使用a的時候直接在符號表中取值。 那麼問題是那又怎樣解釋取地址呢?

    A.編譯過程中若發現使用常量則直接以符號表中的值替換;

    B.編譯過程中若發現對const使用了extern(須要在其它檔案裡使用) 或者 &操作符,則給const常量另外再專門分配儲存空間。

 

 


     如所看到的,對const變數取地址後,為“20”單獨專門分配了空間。而與符號表中的a沒有關係。


2、const與基礎資料類型:

   const int bufsize = 512。bufsize的值不能再被改動。不論什麼試圖為bufsize賦值的行為都將引發錯誤。

由於const的對象一旦建立後其值不能再改變,所以const對象必須初始化。 int i=12;const int ci=i;還能夠利用另外一個對象(是不是const無關緊要)去初始化const對象。。

。int j = ci。一旦拷貝完畢,新的對象和原來的對象就沒有什麼關係了。{ int i = 50; const int j = i; //初始化 int k = j; int m = 100; //j = m; //賦值,編譯錯誤}

    預設狀態下,const對象僅在檔案內有效。當多個檔案裡出現了同名的const對象,事實上等同於在不同檔案定義了獨立的變數。

    假設const對象須要在不同檔案分享權限設定,那就須要對const對象無論是聲明還是定義都加入externkeyword。

    注意僅僅能定義一次:extern const int bufsize = 512。一般被包括在標頭檔。

    在使用時直接聲明:extern const int bufsize;不能再定義,否則出錯。

extern就說明了bufsize並非本檔案專屬,它的定義在別處。


3、const與引用
void main(){   //對常量對象 只能 用 常量引用   const int ci = 100;  //常量對象   const int &ri = ci;  //正確:引用及其相應的對象都是常量   //ri = 100;          //error:ri是對常量的引用   //int &r2 = ci;      //error:將一個很量引用指向一個常量對象,假設正確,那麼將能夠通過改動r2來改變ci的值,ci顯然不能改變。    //常量引用 同意被 綁定到 很量的對象、 字面值、 一般運算式 ————例外1   int i = 50;   const int &CRi1 = i;        //很量的對象   const int &CRi2 = 500;      //字面值   const int &CRi3 = i * 2;    //一般運算式   int r4 = CRi1 * 2;          //正確:CRi1的常量特徵只在運行改變的時候才會發生作用,拷貝賦值並不會改變。一旦拷貝完畢,新的對象和原來的對象就沒有什麼關係了。   //int &r5 = CRi1 * 2;        //error:將一個很量引用指向一個常量對象。假設正確。那麼將能夠通過改動r5來改變CRi1的值,CRi1顯然不能改變。

/* * * * * * * * * *一般來說。引用的類型必須與其所引用對象的類型一致。 *當一個常量引用被綁定到第二種類型上究竟發生了什嗎? * double d = 3.14; const int &ri = d; * const int tmp = d; // 由雙精確度浮點數產生一個暫時的整型常量 const int &ri = d; // 讓ri綁定這個暫時的常量 * * * * * * * * */ //常量引用只對自己可參與的操作做了限定,假設引用的對象是個很量,那麼同意通過其它途徑改變它的值 int j = 10; int &rj = j; //引用rj 綁定 對象j const int &cj = j; //常量引用cj 也綁定 對象j。可是不同意通過cj 去改動j的值 rj = 1000; //通過rj 改動j,j被改動為1000 //cj = 1000; cout << "j: " << j << " ,cj: " << cj << endl; //j: 1000 ,cj: 1000}


const引用傳遞對象(非內建類型):

     (1)效率高:沒有不論什麼新的對象被建立,所以也就不會調用不論什麼的建構函式和解構函式。(內建類型值傳遞方式效率高)

     (2)能夠避免對象被分割:假設衍生類別對象以值傳遞方式賦值給基類。衍生類別的特化性質會被所有分割,只留下一個base類對象。


4、const與指標

      所謂指向常量 的指標或者引用。只是是指標或引用“自以為是”罷了,它們自己認為自己指向了常量,所以自覺地不去改變它所指向的對象的值。(可是常量 的指標或者引用 是能夠 指向很量的,而很量是能夠通過其它途徑改變的)。

      指標是對象,而引用不是!因此。指標本身是不是常量 和 指標所指的是不是一個常量 是兩個相互獨立的問題!

      頂層const——指標本身是個常量!

      底層const——指標所指的對象是個常量。

void main(){    int i = 10, m = 20;    const int ci = 100, cm = 200;     //第一、二個意思一樣,代表一個  常整形數,不論什麼試圖為a、b賦值的行為都將引發錯誤    const int a = 0;        //必須初始化    int const b = 1;              //第三個 c是一個指向常整形數的指標(所指向的記憶體資料不能被改動,可是本身能夠改動)    const int *c1 = &ci;    //int *c2 = &ci;        //存放常量的地址,僅僅能使用指向常量的指標     const int *c = &i;          //*c = m;               //c指向的記憶體資料是const的(c的自我感覺),也就是不能通過 *c “直接改動”的    c = &m;                 //c的值是同意改動的(底層const)。改動c的指向。讓c指向另外一個記憶體空間    cout << *c << endl;     //20      //第四個 d 常指標————指標本身是個常量(指標變數(指向)不能被改動,可是它所指向記憶體空間能夠被改動)    int ii = 0;    int * const d = ?    //d 將一直指向 ii (頂層const),不同意改動 d 的值    *d = 250;               //指標本身是個常量,並不意味著不能通過改動指標所指向的值。

(依賴於所指向的對象) cout << ii << endl; // ii 被改動成250。(d指向的是一個很量) //第五個 e 一個指向常整形的常指標(指標和它所指向的記憶體空間,均不能被改動) const int pi = 123; const int * const e = π //e所指的對象值 和 e自己儲存的那個地址 都不能改變}


5、const與成員函數

    將const實施與成員函數的目的,是為了確認該成員函數可作用於const對象身上(非const成員函數本來就能夠對其對象做不論什麼操作,所以在當中調用一個const成員函數也正確)。

兩個函數假設僅僅是常量性(一個是const成員函數,一個是非const成員函數)不同。也能夠被重載。作為一種良好的編程風格,在聲明一個成員函數時,若該成員函數並不正確資料成員進行改動操作,應儘可能將該成員函式宣告為const 成員函數。在C++中。僅僅有被聲明為const的成員函數才幹被一個const類對象調用。把一個成員函式宣告為const能夠保證這個成員函數不改動資料成員。可是,假設據成員是指標,則const成員函數並不能保證不改動指標指向的對象,編譯器不會把這樣的改動檢測為錯誤。

  int foo(int *test) const;//可看做:int foo(const A *this,int *test); 


6、const與define

          const修飾的常量編譯期間,就確定下來。const常量是由編譯器處理的,提供類型檢查和範圍檢查;宏定義由前置處理器處理。單純的文本替換。

void fun1(){    #define a 10    const int b = 20;    //#undef a  //將宏定義a卸載,限制範圍} void fun2(){    printf("a = %d\n", a);    //printf("b = %d\n", b);   //const定義的b是有範圍的} 


7、const與constexpr

        constexpr:常量運算式,指的是值不會改變而且在編譯過程中就能得到計算結果的運算式。

由資料類型和初始值共同決定。

  

   const int max = 100;         //max是常量運算式   const int limit = max + 1;   //limit是常量運算式   int size = 50;               //size不是常量運算式,僅僅一個普通的int類型   const int sz = get_size();   //sz本身是個常量,但它的值直到執行時才幹確定,所以不是常量運算式    一般說來,假設你認定變數是一個常量運算式。那就把它聲明成constexpr類型。

const int sz = get_size(); //僅僅有get_size()是一個constexptr函數時。才是一條正確的聲明語句。


8、const與auto

       auto通常會忽略掉頂層const。同一時候底層const則會保留。

void main(){   //auto通常會忽略掉頂層const,同一時候底層const則會保留。

int i = 10; const int ci = i; const int &cr = ci; auto b = ci; //b是一個int(ci的頂層const特性被忽略) auto c = cr; //c是一個int(cr是ci的別名,ci的頂層const特性被忽略) auto d = &i; //d是一個整型指標(整數的地址就是指向整數的指標) auto e = &ci; //e是一個指向整型常量的指標(對常量對象 取地址 是一種底層const) //假設希望判斷出的auto類型是一個頂層const。則需明白指出 const auto f = ci; //ci的推演類型是int,f是const //還能夠將引用設為auto,原來的初始化規則仍然適用 auto &g = ci; //g是一個常量引用。綁定到ci //auto &h = 42; //error:顯然不能為一個字面值綁定很量引用。

(怎麼說?h是42的引用?字面量42沒有記憶體空間 沒有辦法做引用) const auto &j = 42; //正確:能夠為常量引用綁定字面值}


9、const與decltype

       decltype處理頂層const和引用的方式與auto不同。假設decltype使用的運算式是一個變數,則decltype返回該變數的類型。
 

  int i = 10;const int ci = i;const int &cr = ci;decltype(ci) x = 0;    //x的類型是const intdecltype(cr) y = x;    //y的類型是const int&。y綁定到x//decltype(cr) z;      //error:z是一個引用,必須初始化 
10、const與迭代器

vector<int> vec;const vector<int>::iterator ite = vec.begin();         //ite 相當於T×  const*ite = 10;                                                                    //正確,改變ite所指之物++ite;                                                                          //錯誤,ite是const的vector<int>::const_iterator conIte = vec.begin(); //conIte相當於 const  T×*conIte = 10;                                                             //錯誤,×conIte是const的++conIte;                                                                   //正確,改變conIte

概覽C++之const

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.