1.函數(shù)重載
在使用函數(shù)之前,我們應(yīng)該聲明它。函數(shù)的聲明被稱為函數(shù)的原型,表示函數(shù)的調(diào)用約定,包括調(diào)用參數(shù)的個(gè)數(shù)和類型,返回值,以及由誰(shuí)去堆棧等等….
關(guān)于函數(shù),我們首先介紹一下函數(shù)重載。函數(shù)重載時(shí)C++引入的一個(gè)新的特性。多個(gè)函數(shù)具有相同的函數(shù)名,這些函數(shù)中只是參數(shù)個(gè)數(shù)和類型不同,它們就構(gòu)成了重載。
我們來(lái)定義一個(gè)函數(shù),返回兩個(gè)數(shù)之間的最大值。
int max(int a, int b);
double max(double a, double b);
如果我們通過(guò)max(20,40);來(lái)調(diào)用的話,它會(huì)根據(jù)參數(shù)的個(gè)數(shù)和類型來(lái)調(diào)用第一個(gè)函數(shù)。我們也可以看通過(guò)max(20.1,40.0);來(lái)調(diào)用第二個(gè)函數(shù)。
2.內(nèi)聯(lián)函數(shù)
函數(shù)調(diào)用,尤其是頻繁的函數(shù)調(diào)用是有一定代價(jià)的,因?yàn)樗殡S著參數(shù)的傳遞,代碼的入棧,堆棧平衡等等….為了避免這種代價(jià),我們可以將函數(shù)聲明為內(nèi)聯(lián)函數(shù)。在聲明為內(nèi)聯(lián)函數(shù)之后,編譯器會(huì)將調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,將內(nèi)聯(lián)函數(shù)的代碼嵌入到調(diào)用內(nèi)聯(lián)函數(shù)的地方。
內(nèi)聯(lián)函數(shù)的使用方法,在函數(shù)聲明的前面加上inline。如:
inline void func(){
int i=0; i++;
}
如果我們?cè)谙旅孢@樣調(diào)用它:
func();
編譯器就會(huì)將代碼嵌入到這個(gè)地方,成了這樣的形式,這樣就沒(méi)有了函數(shù)的調(diào)用。
int i=0; i++;
注意:使用內(nèi)聯(lián)函數(shù)可以節(jié)省運(yùn)行時(shí)間,但是它有一個(gè)缺點(diǎn),它會(huì)使你的應(yīng)用程序體積增大。一般只是將代碼段比較短(三到五行),調(diào)用比較頻繁的函數(shù)聲明為內(nèi)聯(lián)函數(shù)。即使你將一些復(fù)雜的函數(shù)聲明為內(nèi)聯(lián)函數(shù),具體是否嵌入代碼這個(gè)是由編譯器來(lái)決定的。編譯器會(huì)根據(jù)一定的辦法來(lái)判斷它。
3.函數(shù)調(diào)用
C++的內(nèi)存分為兩部分,堆和棧。關(guān)于局部變量,函數(shù)參數(shù)的都是從棧中分配的。棧的特性是先入后出。大家學(xué)習(xí)過(guò)C,對(duì)函數(shù)的調(diào)用原理也比較清楚,函數(shù)的調(diào)用是通過(guò)棧來(lái)實(shí)現(xiàn)的。
下面我們來(lái)回顧一下棧:
比如a調(diào)用了B函數(shù),首先a會(huì)講B函數(shù)需要的參數(shù)入棧,接著會(huì)壓入A中的返回地址,然后在棧中分配局部變量給函數(shù)使用。在函數(shù)執(zhí)行完畢之后,在棧中會(huì)彈出函數(shù)返回地址到a中,此時(shí)分配給B函數(shù)的??臻g被回收。局部變量,函數(shù)參數(shù)占用的??臻g被釋放。
下面我們來(lái)回顧一下堆:
內(nèi)存是有操作系統(tǒng)管理的,應(yīng)用程序可以向操作系統(tǒng)申請(qǐng)。但是應(yīng)用程序向操作系統(tǒng)申請(qǐng)的代價(jià)是很大的,需要考慮到多線程的一些東西。這個(gè)時(shí)候就引入了堆。我們可以把堆比喻成向操作系統(tǒng)批發(fā)內(nèi)存的零售商,它一次性從操作系統(tǒng)批發(fā)了一大片的內(nèi)存,然后零售給我們的應(yīng)用程序使用。因?yàn)闆](méi)有多次從操作系統(tǒng)申請(qǐng),所以操作代價(jià)比較小。堆一般隨著應(yīng)用程序的啟動(dòng)而分配,隨著應(yīng)用程序的退出而銷毀。所以堆在整個(gè)運(yùn)行期間都是可以使用的。
在C中,我們通過(guò)malloc來(lái)分配空間,用free來(lái)釋放空間。
下面來(lái)舉一個(gè)例子。
int *p=(int *)malloc(sizeof(int)*100); //申請(qǐng)一片可以存儲(chǔ)一百個(gè)int變量的值的內(nèi)存
if(!p){ //判斷空間分配是否成功,分配失敗就退出
return 0;
}
free (p); //釋放內(nèi)存
p=NULL; //當(dāng)釋放完這一片內(nèi)存之后,p就已經(jīng)不應(yīng)該再指向這一片內(nèi)存了。
為了防止誤用,我們就把p指向NULL。如果不指向NULL,p就被稱為野指針,野指針會(huì)導(dǎo)致一些問(wèn)題。
在C++中,我們使用new來(lái)分配空間,用delete來(lái)釋放空間。
int *p=new int[100]; //new會(huì)自動(dòng)計(jì)算需要的長(zhǎng)度,分配一連片的內(nèi)存
if(!p){ //判斷空間分配是否成功,分配失敗就退出
return 0;
}
delete []p; //上面是數(shù)組的分配空間,所以釋放的時(shí)候需要在變量名前加[]
p=NULL;
如果只是普通的變量申請(qǐng)和釋放,只需要如此:
int *p=new int;
delete p; //不需要[],對(duì)應(yīng)的申請(qǐng)內(nèi)存的方式一定要匹配。
注意:使用new申請(qǐng)的內(nèi)存在必須使用delete才可以釋放,而釋放的形式也必須匹配。