C const限定符(一)

2021-10-17 15:14:28 字數 3685 閱讀 2425

有時候我們希望定義這樣一種變數,它的值不能被改變,比如需要設定乙個快取區大小:

const int buffsize = 512;
這樣就通過使用const限定符將這個大小設定為了常量,之後,任何為buffsize賦值的操作都將引發錯誤:

buffsize = 1024; //報錯,試圖向const物件寫值
const物件一旦建立後就不能改變,因此必須初始化:

const int i = get_size(); //執行時初始化

const int j = 42; //編譯時初始化

const int k; //未經初始化,報錯

由於物件的型別決定了其上的操作,與非const物件能完成的操作相比,主要的限制就是不能執行改變其內容的操作。

在不改變const物件的操作中,還有一種操作是初始化操作,如果利用乙個物件去初始化另乙個物件,則它們是不是const物件都無所謂:

int i = 42;        //正確

const int ci = i; //正確

int j = ci; //正確

ci的常量特徵僅僅在執行改變ci的操作時才會發揮作用。當用ci去初始化j時,根本無需在意ci是不是常量,拷貝乙個物件的值並不會改變它,一旦拷貝完成,新的物件就和原來的物件沒什麼關係了。 

可以把引用繫結到const物件上,稱為對常量的引用。

const int ci = 1024;

const int &r1 = ci; //正確,都是常量

r1= 42; //報錯,試圖修改常量

int &r2 = ci; //報錯,試圖讓乙個非常量引用去指向乙個常量物件

為什麼r2會報錯呢?因為ci是常量,自然不允許為ci賦值,當然也不允許通過引用的方式去改變ci,因此r2的初始化是錯誤的。假設該初始化合法,那麼就可以通過r2改變ci的值,顯然不正確。

引用要求引用型別和物件的型別一致,這裡存在兩個例外

第乙個例外:初始化常量引用時允許用任意表示式作為初始值,只要該表示式的結果能轉換成引用的型別即可。尤其允許為乙個常量引用繫結非常量的物件、字面值,甚至是個一般表示式。

看下面的例子:

int i = 42;

const int &r1 = i; //正確,允許const int&繫結到乙個普通int物件上

const int &r2 = 42; //正確,r2是乙個常量引用

const int &r3 = r1 * 2; //正確,r3是乙個常量引用

int &r4 = r1 * 2; //錯誤,r4是乙個普通非常量引用

要知道為什麼會發生這種例外,需要明白乙個常量引用繫結到另外一種型別上時到底發生了什麼:

double dval = 3.14;

const int &ri = dval; //合法

const int temp = dval;

const int &ri = temp;

ri繫結了乙個臨時量(臨時建立的未命名的物件),如果ri不是常量,就允許對ri賦值,就會改變所引用物件的值,但此時繫結的是臨時量,無法改變dval的值,歸於非法,也就是說:

double dval = 3.14;

int &ri = dval; //非法

常量引用僅限制了引用可參與的操作,對引用本身是否為常量未做限定。因此,對const的引用可能引用乙個非const的物件。

指向常量的指標不能用於改變其所指物件的值。想存放常量物件的位址,只能使用指向常量的指標。

const double pi = 3.14;

double *ptr = π //錯

const double *cptr = π //對

指標型別同樣要求型別一致,也存在兩個例外:

第乙個例外:允許令乙個指向常量的指標指向乙個非常量物件

double dval = 3.14;

const double *cptr = &dval; //合法

和常量引用一樣,指向常量的指標也沒有規定其所指的物件必須是乙個常量,指向常量的指標僅僅要求不能通過該指標改變物件的值,而沒有規定那個物件的值不能通過其他途徑改變。

int a = 0;

int *const cur = &a;

const double pi = 3.14;

const double *const pip = π

指標是物件,所以可以把指標本身定義為常量。即常量指標。

必須被初始化,把*放在const之前說明指標是乙個常量:隱含:不變的是指標本身而非指向的值

頂層const表示指標本身是個常量

底層const表示指標所指向的物件是乙個常量

更一般的:

頂層const可以表示任意的物件是常量,對任何資料型別都適用。

底層cosnt與指標和引用等符合型別的基本型別部分有關。

指標既可以是頂層const也可以是底層const

int i = 0;

int *const p1 = &i; //不能改變p1的值,頂層const

const int ci = 42; //不能改變ci的值,頂層const

const int *p2 = &ci; //允許改變p2,底層const

const int *const p3 = p2; //靠右的是頂層const,靠左的是底層const

const int &r = ci; //用於宣告引用的const都是底層const

執行物件的拷貝操作時,頂層const不受什麼影響:

i = ci;

p2 = p3; //p2和p3指向的物件型別相同,p3頂層const部分不影響

執行拷貝操作時,拷入和拷出的物件必須具有相同的底層const資格,或者兩個物件的資料型別必須能夠轉換。一般來說非常量可以轉換成常量,反之不行。

int *p = p3;        //錯誤:p3包含底層const的定義,而p沒有

p2 = p3; //正確:p2和p3都是底層const

p2 = &i; //正確:int *能夠裝換成const int*

int &r = ci; //錯誤:普通的int&不能繫結到int常量上

const int &r2 = i; //正確:const int&可以繫結到乙個普通int上

關於C const限定符與define

const限定符修飾的常量無法修改,且在定義的時候必須同時初始化,否則error xcode平台 相比define,const指定的常量有型別,而define只是簡單的字元替換。const修飾的常量只能由const指標來指向,不能用乙個普通的指標指向乙個const修飾的常量 const int a ...

C const 限定符 指標的使用方法

c 中的常量符號const限定符相信大家都比較熟悉它對於基本型別變數的使用方法了 無非有最常用的那種 const type name value 在宣告的時候進行初始化。這個放下不表,看下面 const int a int const a int const a 這三種const限定符指標有什麼區別...

引用限定符

通常,我們在乙個物件上呼叫成員函式,而不管該物件是乙個左值還是乙個右值。例如 string s1 a value s2 another auto n s1 s2 find a 此例中,我們在乙個string右值上呼叫find成員,該string右值是通過連線兩個 string 而得到的。有時,右值的...