函數(shù)默認(rèn)參數(shù)
C++允許函數(shù)設(shè)置默認(rèn)參數(shù),在調(diào)用時(shí)可以根據(jù)情況省略實(shí)參。規(guī)則如下:
- 默認(rèn)參數(shù)只能按照右到左的順序
void print(int a,int b = 100)
{
cout << "a is " << a << endl;
cout << "b is " << b << endl;
}
- 如果函數(shù)同時(shí)有聲明、實(shí)現(xiàn),默認(rèn)參數(shù)只能放在函數(shù)聲明中
void print(int a,int b = 100);
int main(int argc, const char * argv[]) {
print(10);
return 0;
}
void print(int a,int b)
{
cout << "a is " << a << endl;
cout << "b is " << b << endl;
}
-
默認(rèn)參數(shù)的值可以是常量、全局符號(hào)(全局變量、函數(shù)名)
常量上面有所舉例,這里舉一個(gè)全局變量和函數(shù)名作為參數(shù)的列子如下代碼所示:
//定義一個(gè)全局變量
int number = 10000;
void print(int a,int b = number)
{
cout << "a is " << a << endl;
cout << "b is " << b << endl;
}
int main(int argc, const char * argv[]) {
print(10);
return 0;
}
//定義一個(gè)函數(shù)指針
typedef void(*FuncBlock)(int a,int b);
void block(int a,int b)
{
cout << "block a is " << a << endl;
cout << "block b is " << b << endl;
}
void print(int a,FuncBlock fun = block)
{
cout << "a is " << a << endl;
//利用函數(shù)指針真正調(diào)用block函數(shù)
block(10, 10);
}
int main(int argc, const char * argv[]) {
//調(diào)用函數(shù),函數(shù)默認(rèn)為block
print(100);
return 0;
}
注意:函數(shù)默認(rèn)參數(shù)可能會(huì)與函數(shù)重載會(huì)產(chǎn)生沖突,造成調(diào)用不明確,需要避免,建議優(yōu)選選擇函數(shù)默認(rèn)參數(shù)
void print(int a,int b = 100)
{
cout << "a is " << a << endl;
cout << "b is " << b << endl;
}
void print(int a)
{
cout << "a is " << a << endl;
}
int main(int argc, const char * argv[]) {
//調(diào)用錯(cuò)誤
//call to 'print' is ambiguous
print(100);
return 0;
}
內(nèi)聯(lián)函數(shù)
定義:使用inline修飾過的函數(shù)的聲明或者實(shí)現(xiàn),
建議聲明和實(shí)現(xiàn)都增加inline修飾。內(nèi)聯(lián)函數(shù)特點(diǎn)和注意事項(xiàng)如下:
- 編譯器會(huì)將函數(shù)調(diào)用直接展開為函數(shù)體代碼
- 可以減少函數(shù)調(diào)用的開銷
- 會(huì)增大代碼體積
- 內(nèi)聯(lián)函數(shù)盡量不要內(nèi)聯(lián)超過10行代碼的函數(shù)
- 有些函數(shù)即使聲明為inline,也不一定會(huì)被編譯器內(nèi)聯(lián),比如遞歸函數(shù)
內(nèi)聯(lián)函數(shù)和宏,都可以減少函數(shù)調(diào)用的開銷相比宏,內(nèi)聯(lián)函數(shù)多了語法檢測(cè)和函數(shù)特性,宏只是單純的替換, 注意下以下代碼區(qū)別:
#define sum(x) (x + x) //結(jié)果為21
inline int sum(int x) { return x + x; } //結(jié)果為20
int a = 10; sum(a++);
引用
引用相當(dāng)于是變量的別名,包括基本數(shù)據(jù)類型、枚舉、結(jié)構(gòu)體、類、指針、數(shù)組等,都可以有引用。我們先來看下基本類型的引用如下:
int age = 100;
int &rage = age; //rage就是age的引用
rage = 101;//改變引用rage的值,也修改了age的值
cout << rage << endl; //101
cout << age << endl; //101
再來看結(jié)構(gòu)體和指針的引用:
struct Person {
int age;
};
//結(jié)構(gòu)體對(duì)象的引用
Person p;
Person &rp = p;
rp.age = 18;
cout << p.age << endl; //18
//指向結(jié)構(gòu)體對(duì)象指針的引用
Person *pp = new Person();
Person *&rpp = pp; //pp指針的引用rpp
rpp->age = 19;
cout << pp->age << endl; //19
數(shù)組的引用如下:
int array[] = { 10, 20, 30 };
int (&rArray)[3] = array; //這里定義數(shù)組的引用,這里必須指明 數(shù)組元素個(gè)數(shù)
cout << rArray[0] << endl; //10
使用引用的注意事項(xiàng):
- 引用必須初始化,且一旦初始化就不能再改變成其他變量的引用
- 可以用引用初始化另一個(gè)引用,即存在一個(gè)變量多個(gè)別名
- 對(duì)變量引用的操作其實(shí)就是對(duì)變量本身的操作
- 不存在引用的引用,引用數(shù)組,指向引用的指針
//一個(gè)變量多個(gè)引用
int age = 100;
int number = 1000;
int &rage = age; //rage就是age的引用
int &rage1 = rage; //rage1也是age的引用
int &rage2 = age; //rage2也是age的引用
&rage = number; //錯(cuò)誤,引用是不能再被改變成其他變量的引用
int &arry[4]; //錯(cuò)誤,不存在引用數(shù)組
int& *rpage = rage; //錯(cuò)誤,沒有引用類型的指針
int *page = &rage; //正確,對(duì)引用取地址其實(shí)就是對(duì)變量取地址,再用指針指向這個(gè)地址
常引用
我們都知道經(jīng)過const修飾過的變量會(huì)變成常量,跟const的位置也有關(guān),這里我們?cè)賮韽?fù)習(xí)下const修飾變量的用法:
int age = 10;
// *p0是常量,p0不是常量(指針指向地址里面存的值不可改,指針指向地址可以改)
const int *p0 = &age;
// *p1是常量,p1不是常量(跟上述一樣)
int const *p1 = &age;
// p2是常量,*p2不是常量(指針指向地址里面存的值可以改,指針指向地址不可改)
int * const p2 = &age;
// *p3是常量,p3是常量(指針指向地址里面存的值不可改,指針指向地址不可改)
const int * const p3 = &age;
// *p4是常量,p4是常量(跟上述一樣)
int const * const p4 = &age;
通過const修飾的結(jié)構(gòu)體對(duì)象,代碼如下:
struct Person {
int age;
};
Person per1 = { 10 };
Person per2 = { 20 };
//此時(shí)nPer指向不可更改,nPer指向?qū)ο罄锩娴膬?nèi)容可以更改
Person * const pPer = &per1;
*pPer = per2; //正確
(*pPer).age = 30;//正確
pPer->age = 40;//正確
pPer = &per2; //錯(cuò)誤,不可改
//此時(shí)nPer1指向可以更改,但是nPer1指向?qū)ο蟛豢筛?const Person * pPer1 = &per1;
*pPer1 = per2; //錯(cuò)誤
(*pPer1).age = 30;//錯(cuò)誤
pPer1->age = 40;//錯(cuò)誤
pPer1 = &per2;//正確
常引用:被const修飾的引用不可更改,稱為常引用
int age = 10;
int number = 20;
//定義一個(gè)常應(yīng)用
const int &rage = age;
rage = 20;//無法修改,報(bào)錯(cuò)
&rage = number;//無法修改,引用沒有這種寫法
//定義一個(gè)const指針
const int * const page = &age;
*page = 20;//無法修改,報(bào)錯(cuò)
page = &number//無法修改,報(bào)錯(cuò)
最后補(bǔ)充一個(gè)常引用知識(shí)點(diǎn):當(dāng)常引用指向了不同類型的數(shù)據(jù)時(shí),會(huì)產(chǎn)生臨時(shí)變量,即引用指向的并不是初始化時(shí)的那個(gè)變量
int age = 10;
const int &rAge = age;
age = 30;
//age is 30
cout << "age is " << age << endl;
//rAge is 10
cout << "rAge is " << rAge << endl;
細(xì)心同學(xué)通過上述代碼發(fā)現(xiàn)了引用和指針達(dá)到的效果好像差不多,既然存在了指針,為什么C++還要用引用呢?這就涉及到引用的本質(zhì),它存在的價(jià)值是什么?我們后面再介紹,敬請(qǐng)期待。