const限定符
const是一種限定符,被const所限定的變數其值不可以被改變,
const的初始化
由于const一旦創建其值就不能夠被改變,所以我們必須對其進行初始化
const int a;//錯誤,const變數必須進行初始化!
const int b=10;//正確,編譯時初始化
const int c=get_size();//正確,運行時初始化
相同型別的變數相互初始化時,不論變數是否被const限定我們都可以進行隨意的相互拷貝,因為在拷貝程序中我們只會用到等式右邊變數的右值屬性,無須在意其是否可以改變,
int m = 5;
const int n = m;
int j = n;
const與指標
頂層const與底層const
對于指標來說,由于其指向另一片記憶體的特點,有三種不同的const情況,即:
- 指向常量的指標(const int *)
- 常量指標(int * const)
- 指向常量的常量指標(const int *const)
我們一般稱符合第一種情況的為具有底層const屬性,
符合第二種情況的為具有頂層const屬性,
第三種情況兼而有之,
關于帶有const的指標的相互賦值(或者初始化)問題
- 頂層const并不會影響變數間的相互拷貝(原因是頂層const只保證自身的值不會改變,const沒有改變自身的變數型別,在拷貝時只是使用該型別的右值),
- 如果等號右邊是底層const,那么等號左邊必須保證為相同的底層const(或者等號右邊的型別可以轉換成等號左邊的型別),否者運算式無法通過編譯,
關于底層與頂層const的一些想法
const的底層與頂層屬性似乎只在指標上存在,但是c++primer中有這樣的代碼和注釋:
const int ci=1,&cr=ci;
auto b=ci;//b是一個整數(ci的頂層const特性被忽略掉了)
auto c=cr;//c是一個整數(cr是ci的別名,ci本身是一個頂層const)
這段代碼是為了說明auto說明符一般會忽略掉頂層const的特性,在注釋中明確寫著ci本身是一個頂層const,
這也與我的看法一致,底層與頂層const實際上并不是指標所特有的,只要是不能改變物件自身的物件都具有頂層const,而不能改變自己所指向的物件的物件都具有底層const,
從這個角度看,參考實際上自帶頂層const,
底層const的隱式轉換
上面提到,只有在等號右邊和等號左邊的型別具有相同的底層const屬性,才可以進行賦值或者初始化,
然而有些時候等號右邊可能并不具有和等號左邊一致的底層const卻依然可以成立,這是因為等號右邊的型別發生了隱式轉換從而具有了和等號左邊型別相同底層const屬性,
例如:
int i=5;
int *p=&i;
const int *cp=p//int*隱式轉換稱為了const int*
為什么int *轉換成const int *被設定為合法的呢,因為在將int *轉換為const int *的程序中用戶的權限變小了,在這一轉換程序中并不會使程式變得不可靠,
由此我們可以得知非底層const的指標是可以通過隱式轉換轉變成底層const的,
const與參考
可以把參考系結在const的變數上,稱為const的參考,對常量的參考,
與普通的參考不同的是,對常量的參考不能被用作修改它所系結的物件
const int ci=5;
const int &r=ci;
r=6//錯誤不可以通過常參考來修改值
int &r2=ci//錯誤,試圖讓一個非常量參考指向一個常量物件,
const參考的初始化
我們知道對于參考來說初始化時一定要用一個物件初始化,且該物件的型別需要與之匹配,
但是const的參考是個例外,在初始化常量參考時允許用任意運算式作為初始值,只要該運算式的結果能轉換成參考的型別即可,甚至允許為一個常量參考系結非常量的物件、字面值或者是運算式,
int i=42;
const int &r1=i;//允許將const int&系結到一個普通int物件上
const int &r2=3.14;//正確:r2是一個常量參考
const int &r3=r1*2;//正確:r3是一個常量參考
int &r4 =r1*2;//錯誤,非常量參考不能用運算式初始化,
C++primer中給出了可以這么做的原因:
要想理解這種例外情況的原因,最簡單的方法是弄清楚當一個常量參考被系結到另外一種型別上都時到底發生了什么:
double dval=3.14;
const int &ri=dval;
此處ri參考了一個int型的數,對ri的操作應該是整數運算,但dval卻是一個雙精度浮點數而非整數,因此為了確保讓ri系結一個整數,編譯器把上述代碼變成了如下形式:
const int temp=dval;//由雙精度浮點數生成一個臨時的整型常量
const int &ri=temp;//讓ri系結這個臨時量
在這種情況下,ri系結了一個臨時量物件,所謂臨時量物件就是當編譯器需要一個空間來暫存運算式的求值結果時臨時創建的一個未命名的物件,C++程式員們常常把臨時量物件簡稱為臨時量,
const與auto型別說明符
auto型別說明符是C++11中新引入的型別說明符,可以自動推斷型別,
編譯器推斷出來的auto型別有時候和初始值的型別并不完全一樣,編譯器會適當的改變結果型別使其更符合初始化規則,
auto在推斷帶有const的物件時,編譯器一般會忽略掉頂層const,同時底層const則會保留下來,
另外對于參考由于參考沒有真正的物體,所以如果用一個參考來初始化auto型別時,auto實際上為參考所指向的物件的型別,而非參考,如果要說明其為參考型別,需要使用auto&,
const int ci=i,&cr=ci;
auto b=ci;//b是一個整數(ci的頂層const特性被忽略掉了)
auto c=cr;//c是一個整數(cr是ci的別名,ci本身是一個頂層const)
auto d=&i;//d是一個整型指標(整數的地址就是指向整數的指標)
auto e=&ci;//e是一個指向整數常量的指標(對常量物件取地址是一種底層const)
如果希望推斷出的auto型別是一個頂層const,需要明確指出:
const auto f=ci;//ci的推演型別為int,f是const int,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/61736.html
標籤:C++
下一篇:樹結構基礎
