const形參和實參


當形參是const時,必須要注意關於頂層const的討論。如前所述,頂層const的作用於對象本身:

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

int i=ci;   //正確:當拷貝ci時,忽略了它的頂層const

int *const p=&i;  //const是頂層的,不能給p賦值

*p=0;    //正確:通過p改變對象的內容是允許的,現在i變成了0

和其他初始化過程一樣,當用實參初始化形參時會忽略掉頂層const。換句話說,形參的頂層const被忽略掉了。當形參有頂層const時,傳給它的常量對象或者非常量對象都是可以的

void fcn(const int i){  /*fcn能夠讀取i,但是不能向i寫值*/}

調用fcn函數時,既可以傳入const int也可以傳入int。忽略掉形參的頂層const可以產生意想不到的結果

void fcn(const int i) {/*fcn能夠讀取i,但是不能向i寫值*/}

void fcn(int i)  {/*....*/}//錯誤:重復定義了fdn(int)

在C++語言中,允許我們定義若干具有相同名字的函數,不過前提是不同函數的形參列表應該有明顯的區別。因為頂層const被忽略了,所以在上面的代碼中傳入兩個fcn函數的參數可以完全一樣。因此第二個fcn是錯誤的,盡管形式上由差異,但實際上它的形參和第一個fcn的形參沒什么不同。

 

指針或引用形參與const

形參的初始化方式和變量的初始化方式是一樣的,所以回顧通用的初始化規則有助於理解下面的知識。我們可以使用非常量初始化一個底層的const對象,但是反過來不行;同時一個普通的引用必須用同類型的對象初始化

int i=42;

const int *cp=&i;  //正確:但是cp不能改變i

const int &r=i;   //正確:但是r不能改變i

const int &r2=42;   //正確

int  *p=cp;    //錯誤:p的類型和cp的類型不匹配

int &r3=r;    //錯誤:r3的類型和r的類型不匹配

int  &r4=42;  //錯誤:不能用字面值初始化一個非常量引用

將同樣的初始化規則應用到參數傳遞上可得如下形式:

int i=0;

const int ci=i;

string::size_type ctr=0;

void reset(int &i);

reset(&i);  //調用形參類型是int *的reset函數

reset(&ci);  //錯誤:不能用指向const int對象的指針初始化int *

reset(i);   //調用參數類型是int&的reset函數

reset(ci);  //錯誤:不能把普通引用綁定到const對象ci上

reset(42);  //錯誤:不能把普通引用綁定到字面值上

reset(ctr); //錯誤:類型不匹配,ctr是無符號類型

//find_char的第一個形參是對常量的引用

find_char("hello world",'o',ctr);//可以綁定到字面值常量上

要想調用引用版本的reset,只能使用int類型的對象,而不能使用字面值、求值結果為int的表達式、需要轉換的對象或者const int類型的對象。類似的,要想調用指針版本的reset只能使用int*。

另一方面,我們能傳遞一個字符串字面值作為find_char的第一個實參,這是因為改函數的引用形參是常量引用,而C++允許我們用字面值初始化常量引用。

 

盡量使用常量引用

把函數不會改變的形參定義成(普通的)引用是一種比較常見的錯誤,這么做帶來給函數的調用者一種誤導,即函數可以修改它的實參的值。此外,使用引用而非常量引用也會極大地限制函數所能接受的實參類型。就像剛剛看到的,我們不能把const對象、字面值或者需要類型轉換的對象傳遞給普通的引用形參

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM