const形參和實參

當形參是const時,必需要注意關於頂層const的討論。如前所述,頂層const的做用於對象自己:函數

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

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

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

*p=0;    //正確:經過p改變對象的內容是容許的,如今i變成了0ci

和其餘初始化過程同樣,當用實參初始化形參時會忽略掉頂層const。換句話說,形參的頂層const被忽略掉了。當形參有頂層const時,傳給它的常量對象或者很是量對象都是能夠的字符串

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

調用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對象、字面值或者須要類型轉換的對象傳遞給普通的引用形參

相關文章
相關標籤/搜索