C++中const總結[轉]
閱讀全文(355) |
回復(1) |
引用通告(0) |
編輯一、對于基本聲明
1.const int r=100; //標準const變量聲明加初始化,因為默認內部連接所以必須被初始化,其作用域為此文件,編譯器經(jīng)過(guò)類(lèi)型檢查后直接用100在編譯時(shí)替換。
2.extend const int r=100; //將const改為外部連接,作用于擴大至全局,編譯時(shí)會(huì )分配內存,并且可以不進(jìn)行初始化,僅僅作為聲明,編譯器認為在程序其他地方進(jìn)行了定義。
3.const int r[ ]={1,2,3,4};
struct S {int a,b;};
const S s[ ]={(1,2),(3.4)}; //以上兩種都是常量集合,編譯器會(huì )為其分配內存,所以不能在編譯期間使用其中的值,例如:int temp[r[2]];這樣的編譯器會(huì )報告不能找到常量表達式
二、對于指針
1.const int *r=&x; //聲明r為一個(gè)指向常量的x的指針,r指向的對象不能被修改,但他可以指向任何地址的常量。
2.int const *r=&x; //與用法1完全等價(jià),沒(méi)有任何區別。
3.int * const r=&x; //聲明r為一個(gè)常量指針,他指向x,r這個(gè)指針的指向不能被修改,但他指向的地址的內容可以修改。
4.const int * const r=&x; //綜合1、3用法,r是一個(gè)指向常量的常量型指針。
三、對于類(lèi)型檢查
可以把一個(gè)非const對象賦給一個(gè)指向const的指針,因為有時(shí)候我們不想從這個(gè)指針來(lái)修改其對象的值;但是不可以把一個(gè)const對象賦值給一個(gè)非const指針,因為這樣可能會(huì )通過(guò)這個(gè)指針改變指向對象的值,但也存在使這種操作通過(guò)的合法化寫(xiě)法,使用類(lèi)型強制轉換可以通過(guò)指針改變const對象:
const int r=100;
int * ptr = const_cast(&r); //C++標準,C語(yǔ)言使用:int * ptr =(int*)&r;
四、對于字符數組
如char * name = “china”; 這樣的語(yǔ)句,在編譯時(shí)是能夠通過(guò)的,但是”china”是常量字符數組,任何想修改他的操作也能通過(guò)編譯但會(huì )引起運行時(shí)錯誤,如果我們想修改字符數組的話(huà)就要使用char name[ ] = “china”; 這種形式。
五、對于函數
1.void Fuction1 ( const int r ); //此處為參數傳遞const值,意義是變量初值不能被函數改變
2.const int Fuction1 (int); //此處返回const值,意思指返回的原函數里的變量的初值不能被修改,但是函數按值返回的這個(gè)變量被制成副本,能不能被修改就沒(méi)有了意義,它可以被賦給任何的const或非const類(lèi)型變量,完全不需要加上這個(gè)const關(guān)鍵字。但這只對于內部類(lèi)型而言(因為內部類(lèi)型返回的肯定是一個(gè)值,而不會(huì )返回一個(gè)變量,不會(huì )作為左值使用),對于用戶(hù)自定義類(lèi)型,返回值是常量是非常重要的,見(jiàn)下面條款3。
3.Class CX; //內部有構造函數,聲明如CX(int r =0)
CX Fuction1 () { return CX(); }
const CX Fuction2 () { return CX(); }
如有上面的自定義類(lèi)CX,和函數Fuction1()和Fuction2(),我們進(jìn)行如下操作時(shí):
Fuction1() = CX(1); //沒(méi)有問(wèn)題,可以作為左值調用
Fuction2() = CX(1); //編譯錯誤,const返回值禁止作為左值調用。因為左值把返回值作為變量會(huì )修改其返回值,const聲明禁止這種修改。
4.函數中指針的const傳遞和返回:
int F1 (const char * pstr); //作為傳遞的時(shí)候使用const修飾可以保證不會(huì )通過(guò)這個(gè)指針來(lái)修改傳遞參數的初值,這里在函數內部任何修改*pstr的企圖都會(huì )引起編譯錯誤。
const char * F2 (); //意義是函數返回的指針指向的對象是一個(gè)const對象,它必須賦給一個(gè)同樣是指向const對象的指針。
const char * const F3(); //比上面多了一個(gè)const,這個(gè)const的意義只是在他被用作左值時(shí)有效,它表明了這個(gè)指針除了指向const對象外,它本身也不能被修改,所以就不能當作左值來(lái)處理。
5.函數中引用的const傳遞:
void F1 ( const X& px); //這樣的一個(gè)const引用傳遞和最普通的函數按值傳遞的效果是一模一樣的,他禁止對引用的對象的一切修改,唯一不同的是按值傳遞會(huì )先建立一個(gè)類(lèi)對象的副本,然后傳遞過(guò)去,而它直接傳遞地址,所以這種傳遞比按值傳遞更有效。
**另外只有引用的const傳遞可以傳遞一個(gè)臨時(shí)對象,因為臨時(shí)對象都是const屬性,且是不可見(jiàn)的,他短時(shí)間存在一個(gè)局部域中,所以不能使用指針,只有引用的const傳遞能夠捕捉到這個(gè)家伙。
六、對于類(lèi)
1.首先,對于const的成員變量,只能在構造函數里使用初始化成員列表來(lái)初始化,試圖在構造函數體內進(jìn)行初始化const成員變量會(huì )引起編譯錯誤。初始化成員列表形如:
2.X:: X ( int ir ): r(ir) {} //假設r是類(lèi)X的const成員變量
2.const成員函數。提到這個(gè)概念首先要談到const對象,正象內置類(lèi)型能夠定義const對象一樣(const int r=10;),用戶(hù)自定義類(lèi)型也可以定義const對象(const X px(10);),編譯器要保證這個(gè)對象在其生命周期內不能夠被改變。如果你定義了這樣的一個(gè)const對象,那么對于這個(gè)對象的一切非const成員函數的調用,編譯器為了保證對象的const特性,都會(huì )禁止并在編譯期間報錯。所以如果你想讓你的成員函數能夠在const對象上進(jìn)行操作的話(huà),就要把這個(gè)函數聲明為const成員函數。假如f( )是類(lèi)中的成員函數的話(huà),它的聲明形如:
int f( ) const; //const放在函數的最后,編譯器會(huì )對這個(gè)函數進(jìn)行檢查,在這個(gè)函數中的任何試圖改變成員變量和調用非const成員函數的操作都被視為非法
注意:類(lèi)的構造和析構函數都不能是const函數。
3.建立了一個(gè)const成員函數,但仍然想用這個(gè)函數改變對象內部的數據。這樣的一個(gè)要求也會(huì )經(jīng)常遇到,尤其是在一個(gè)苛刻的面試考官那里。首先我們要弄清楚考官的要求,因為有兩種方法可以實(shí)現,如果這位考官要求不改變原來(lái)類(lèi)的任何東西,只讓你從當前這個(gè)const成員函數入手,那么你只有使用前面提到的類(lèi)型強制轉換方法。實(shí)例如下:
//假如有一個(gè)叫做X的類(lèi),它有一個(gè)int成員變量r,我們需要通過(guò)一個(gè)const成員函數f( )來(lái)對這個(gè)r進(jìn)行++r操作,代碼如下
void X::f( ) const
{ (const_cast(this)) -> ++r; } //通過(guò)this指針進(jìn)行類(lèi)型強制轉換實(shí)現
另外一種方法就是使用關(guān)鍵字:mutable。如果你的成員變量在定義時(shí)是這個(gè)樣子的:
mutable int r ;
那么它就告訴編譯器這個(gè)成員變量可以通過(guò)const成員函數改變。編譯器就不會(huì )再理會(huì )對他的檢查了。