C++ 11—const用法(C++ primer讀書筆記)

C++ 11—const用法指針

有時咱們但願定義一個這樣的變量,它的值不能被改變。例如,用一個變量來表示緩衝區的大小。使用變量的好處是當咱們以爲緩衝區大小再也不適合時,很容易對其進行調整。(直接改變const定義的值便可)爲了實現這一要求,能夠用關鍵字const對變量加以限定。code

const int buffSize = 512;   //輸入緩衝區的大小

這樣buffSize就定義成爲一個常量。任何試圖爲buffSize賦值的行爲都會引起錯誤:對象

buffSize = 512;     //錯誤,試圖向const對象寫值

由於const對象一旦建立後其值就不能再改變,因此cosnt對象必須初始化。ip

  • 其實const主要限定就是隻能在const類型對象上執行不改變其內容的操做ci

  • 默認狀態下,const對象僅在文件內有效(當多個文件中出現同名的const變量時,其實等同於在不一樣文件中分別定義了獨立的變量)//解決辦法:對於const變量不論是聲明仍是定義都添加extern關鍵字編譯器

1、const引用pip

引用也能夠綁定到cosnt對象上,就像綁定到其餘對象上同樣,這稱爲對常量的引用。與普通引用不一樣的是,對常量的引用不能被用做修改它所綁定的對象。編譯

const int ci = 1024;
const int &r1 = ci;     //正確:引用及其對應的對象都是常量
r1 = 42;        //錯誤:r1是對常量的引用,不能在對其進行賦值(改變常量的操做)
int &r2 = ci;       //錯誤:試圖讓一個很是量引用ci常量對象
  • 初始化和對const的引用
    引用的類型必須與其所引用對象的類型一致,可是有例外:
    • 初始化常量引用時容許用任意表達式做爲初始值,只要該表達式的結果能轉化成引用的類型便可。尤爲容許爲一個常量引用綁定很是量對象、字面值、甚至是一個通常表達式。
      舉個栗子:dva

      const i = 42;
      const int &r1 = i; //容許將const int& 綁定到一個普通int對象上
      const int &r2 = 42; //正確:r2是一個常量引用
      const int &r3 = r12; //正確:r3是一個常量引用
      int &r4 = r1
      2; //錯誤:r4是一個普通的很是量引用,而r1是一個常量引用變量

Why Wrong?

舉個栗子來解釋:

double dval = 3.14;
const int &ri = dval;

此處ri引用了一個int型的數,對ri的操做應該是整數運算,但dval倒是一個雙精度浮點數而非整數。所以爲了確保讓ri綁定一個整數,編譯器把上述代碼變成以下形式:

const int temp = dval;      //由雙精度浮點數生成一個臨時的整形常量,即3;
cosnt int &ri = temp;       //讓ri綁定這個臨時變量

在這種狀況下,ri綁定了一個臨時量(temporary)對象。所謂的臨時量對象就是當編譯器須要一個空間來暫存表達式的求值結果時臨時建立的一個未命名的對象。

2、const與指針的故事

與引用同樣,也可讓指針指向常量或很是量。相似於常量引用,指向常量的指針(pointer to const)不能用於改變其所指向的對象的值。要想存放常量對象的地址,只能使用指向常量的指針:

const double pi = 3.14;     //pi是個常量,它的值不能改變
double *ptr = π          //錯誤:ptr是一個普通指針
const double *cptr = π   //正確:cptr能夠指向一個雙精度常量
*ptr = 42;                  //錯誤:不能給*cptr賦值

指針的類型必須與其所指向的對象類型一致,可是有兩個例外。第一種例外狀況是容許令一個指向常量的指針指向一個很是量對象。

double dval = 3.14;     //dval是一個雙精度浮點數,它的值能夠改變
cptr = &dval;           //正確:可是不能經過cptr改變dval的值

和常量引用同樣,指向常量的指針也沒有規定其所指向的對象必須是一個常量。所謂指向常量的指針僅僅要求不能經過該指針來改變所指向的對象的值(其實仍是能夠經過其餘方式改變被指向對象的值)。

const指針

指針是對象而引用不是,所以就像其餘對象類型同樣,容許把指針自己定義爲常量,即爲常量指針。指針常量必須初始化,並且一旦初始化完成,則它的值(也就是存放在指針中的那個地址)就不能再改變了。

int errNumb = 0;        
int *const curErr = &errNumb;       //curErr將一直指向errNumb
const double pi = 3.14159;
const double *const pip = π      //pip是一個指向常量的常量指針

錯誤的栗子:

*pip = 2.72;    //錯誤:pip是一個指向常量的常量指針(錯在指向常量就不能再向常量賦值)
                
if(*curErr) {    //若是curErr所指向的對象(也就是errNumb)的值不爲零
  errorHandler();
  *curErr = 0;      //正確:把curErr所指向的對象的值重置(curErr自己保存的地址不能改變,curErr是常量指針)
}

3、頂層const

如前所述,指針自己是一個對象,他又能夠指向另一個對象。所以,指針自己是否是常量以及指針所指的是否是一個常量就是倆個相互獨立的問題。用名詞頂層const(top-level const)表示指針自己是一個常量,而用名詞底層cosnt(low-level const)表示指針所知的對象是一個常量。

相關文章
相關標籤/搜索