const
const的出現,把一個變量轉換為一個常量,這樣就避免了變量指派在程式中由于過失而被改變,因為const是隻讀的。
1 定義const
因為常量在定義後不能被修改,是以const對象在定義時必須初始化。
const std::string s = "welcome";//正确
const int i;//錯誤
2 const對象預設為檔案的局部變量
//file_1
int i ;
//file_2
extern int i; //使用file_1中的i
i++; //非const對象在file_2中仍然可以使用
除非特别說明,在全局作用域聲明的const變量是定義該對象的檔案的局部變量,不能被其他檔案通路,隻存在于定義它的檔案中。
非const變量預設為extern。要使const變量能在其他檔案中使用,必須顯示地定義為extern const
//file_1
extern const int j = ;
//file_2
extern const int j;//使用file_1中的j
while(j!=)
{...}
引用
1 引用隻是别名
引用隻是它綁定的對象的别名,所有在作用在引用上的操作其實都是作用在該引用綁定的對象上。
引用必須用與該引用同類型的對象初始化,且必須定義時一并初始化
int i = ,j=;
int &k = i; //正确
int &k; //錯誤
int &k = ; //錯誤
int &m = i,&n = j;//定義多個引用
int &m = i,n = j;//m是引用,n是int
const引用
const引用是指向const對象的引用
1 const引用的聲明及初始化
1 能用同類型對象去初始化,且聲明時初始化
const int i = ;
const int &j = i;//用同類型對象初始化
int &m = i;//錯誤,m是非const引用,指向的值可修改,而i是const對象,不可修改,将普通的引用綁定到const對象是不合法的。
2 也能初始化為不同但相關類型*的對象或者右值(隻有const引用能這樣,非const引用依舊遵循隻能用同類型對象去初始化)
int i = ;
const int &j = ;//合法
const int &m = &i+j;//合法
綁定到不同類型時;
double i = ;
const int &j = i;
編譯器會把代碼轉換為如下形式的編碼:
int temp = i;
const int &j = temp;//僅允許const引用綁定到需要臨時變量作為媒介來完全綁定過程的值,因為const引用是隻讀的。
const形參
1 若函數形參為非引用非const,則既可以給該函數傳遞const實參也可以傳遞非const的實參。
int rgcd(int a,int b)
{...}
const int i=,j =;
int k = rgcd(,);//合法
2 若形參定義為非引用的const類型,則在函數中不可改變實參的局部副本,但由于實參仍然是以副本的形式傳遞,是以既可以傳遞const實參,也可以傳遞非const實參
int fcn(const int i)
{...}
引用形參
引用形參和指針形參的出現,主要為解決複制實參的局限性
不宜複制實參的情況包括:
- 當需要在函數中修改實參的值
- 當需要以大型對象作為實參傳遞時。對實際應用而言,複制對象所付出的時間和存儲空間代價往往過大
- 當沒有辦法實作對象的複制時
指針形參
形參是指針形參的,傳遞對象時是複制指針實參。如果函數是将新的指針值賦給形參,主調函數使用的實參指針的值沒有改變。
void reset(int *ip)
{
*ip = ;//使ip指向的對象值為
ip = ;//僅改變ip在該函數中的值,實參并未改變
}
int i = ;
int *p = &i;
cout<<"i:"<<*p<<'\n'; //i:
reset(p);
cout<<"i:"<<*p<<endl;//i:
如果要保護指針指向的值,則形參要定義為const對象的指針
void use_ptr(const int *p)
{
//隻能讀取指針指向的值,而不能改變至指針指向的值
}
既可以用int 也可以用const int 的實參來調用use_ptr函數,但僅能将int *類型的實參傳遞給reset函數。可以将指向const對象的指針初始化指向非const對象,但是不可以讓指向非const對象的指針指向const對象
引用形參
與所有引用一樣,引用形參直接關聯到其所綁定的對象,而并非這些對象的副本。
-
使用引用形參傳回額外的資訊
比如解決函數有不止一個内容需要傳回
-
利用const引用避免複制
如果使用引用的唯一目的是避免複制實參,則應将形參定義為const引用類型。
- 更靈活的指向const的引用
應該将不需要修改的引用形參定義為const引用。普通的非const引用形參在使用時不太靈活,這樣的形參既不能用const對象初始化,也不能用字面值實參或者産生右值的表達式的實參初始化。//函數形參為非const引用 int incr(int &val) { return val++; } int main() { short v1 = ; const int v2 = ; int v3 = incr(v1); //錯誤 v1不是int v3 = incr(v2); //錯誤,v2是const v3 = incr(); //錯誤,0是常量,不是左值 v3 = incr(v1+v2); //錯誤,加起來也不是左值 int v4 = incr(v3); //正确,v3是int }
-
傳遞指向指針的引用
通過實作兩個指針的交換,實作交換兩個整數的函數
int *&v1 從右至左了解,隻是傳進ptrwasp 函數的任一指針的别名void ptrswap(int *&v1, int *&v2) { int *temp = v2; v2 = v1; v1 = temp; }
int main() { int i = ; int j = ; int *pi = &i ; int *pj = &j ; cout<<"Before ptrswap():\t *pi:"<< *pi<<"\t *pj:"<< *pj<<endl; ptrswap(pi,pj); cout<<"After ptrswap():\t *pi:"<< *pi<<"\t *pj:"<< *pj<<endl; return ; }
執行結果為:
Before ptrswap(): *pi :10 *pj:20
After ptrswap(): *pi :20 *pj:10
即指針的值被調換了。之前pi指向i,pj指向j,現在pi指向j,pj指向i。