十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
目錄
8.1 C++內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)是C++為提高程序運(yùn)行速度所做的一項(xiàng)改進(jìn)。常規(guī)函數(shù)和內(nèi)聯(lián)函數(shù)之間的主要區(qū)別不在于編寫(xiě)方式,而在于C++編譯器如何將它們組合到程序中。要了解內(nèi)聯(lián)函數(shù)與常規(guī)函數(shù)之間的區(qū)別,必須深入到程序內(nèi)部。
編譯過(guò)程的最終產(chǎn)品是可執(zhí)行程序——由一組機(jī)器語(yǔ)言指令組成。運(yùn)行程序時(shí),操作系統(tǒng)將這些指令載入到計(jì)算機(jī)內(nèi)存中,因此每條指令都有特定的內(nèi)存地址。計(jì)算機(jī)隨后將逐步執(zhí)行這些指令。有時(shí)(如有循環(huán)或分支語(yǔ)句時(shí)),將跳過(guò)一些指令,向前或向后跳到特定地址。常規(guī)函數(shù)調(diào)用也使程序跳到另一個(gè)地址(函數(shù)的地址),并在函數(shù)結(jié)束時(shí)返回。下面更詳細(xì)地介紹這一過(guò)程的典型實(shí)現(xiàn)。執(zhí)行到函數(shù)調(diào)用指令時(shí),程序?qū)⒃诤瘮?shù)調(diào)用后立即存儲(chǔ)指令的內(nèi)存地址,并將函數(shù)參數(shù)復(fù)制到堆棧(為此保留的內(nèi)存塊),跳到標(biāo)記函數(shù)起點(diǎn)的內(nèi)存單元,執(zhí)行函數(shù)代碼(也許還需將返回值放入到寄存器中),然后跳回到地址被保存的指令處(這與閱讀文章時(shí)停下來(lái)看腳注,并在閱讀完腳注后返回到以前閱讀的地方類似)。來(lái)回跳躍并記錄跳躍位置意味著以前使用函數(shù)時(shí),需要一定的開(kāi)銷。
C++內(nèi)聯(lián)函數(shù)提供了另一種選擇。內(nèi)聯(lián)函數(shù)的編譯代碼與其他程序代碼“內(nèi)聯(lián)”起來(lái)了。也就是說(shuō),編譯器將使用相應(yīng)的函數(shù)代碼替換函數(shù)調(diào)用。對(duì)于內(nèi)聯(lián)代碼,程序無(wú)需跳到另一個(gè)位置處執(zhí)行代碼,再跳回來(lái)。因此,內(nèi)聯(lián)函數(shù)的運(yùn)行速度比常規(guī)函數(shù)稍快,但代價(jià)是需要占用更多內(nèi)存。如果程序在10個(gè)不同的地方調(diào)用同一個(gè)內(nèi)聯(lián)函數(shù),則該程序?qū)摵瘮?shù)代碼的10個(gè)副本(參見(jiàn)下圖)。
應(yīng)有選擇地使用內(nèi)聯(lián)函數(shù)。如果執(zhí)行函數(shù)代碼的時(shí)間比處理函數(shù)調(diào)用機(jī)制的時(shí)間長(zhǎng),則節(jié)省的時(shí)間將只占整個(gè)過(guò)程的很小一部分。如果代碼執(zhí)行時(shí)間很短,則內(nèi)聯(lián)調(diào)用就可以節(jié)省非內(nèi)聯(lián)調(diào)用使用的大部分時(shí)間。另一方面,由于這個(gè)過(guò)程相當(dāng)快,因此盡管節(jié)省了該過(guò)程的大部分時(shí)間,但節(jié)省的時(shí)間絕對(duì)值并不大,除非該函數(shù)經(jīng)常被調(diào)用。
要使用這項(xiàng)特性,必須采取下述措施之一:
通常的做法是省略原型,將整個(gè)定義(即函數(shù)頭和所有函數(shù)代碼)放在本應(yīng)提供原型的地方。
程序員請(qǐng)求函數(shù)作為內(nèi)聯(lián)函數(shù)時(shí),編譯器并不一定會(huì)滿足這種要求。它可能認(rèn)為該函數(shù)過(guò)大或注意到函數(shù)調(diào)用了自己(內(nèi)聯(lián)函數(shù)不能遞歸),因此不將其作為內(nèi)聯(lián)函數(shù);而有些編譯器沒(méi)有啟用或?qū)崿F(xiàn)這種特性。
程序清單8.1通過(guò)內(nèi)聯(lián)函數(shù)square()(計(jì)算參數(shù)的平方)演示了內(nèi)聯(lián)技術(shù)。注意到整個(gè)函數(shù)定義都放在一行中,但并不一定非得這樣做。然而,如果函數(shù)定義占用多行(假設(shè)沒(méi)有使用冗長(zhǎng)的標(biāo)識(shí)符),則將其作為內(nèi)聯(lián)函數(shù)就不太合適。
程序清單8.1 inline.cpp
//inline.cpp -- using an inline function
#include//an inline function definition
inline double square(double x) { return x * x; }
int main()
{
using namespace std;
double a, b;
double c = 13.0;
a = square(5.0);
b = square(4.5 + 7.5); //can pass expressions
cout<< "a = "<< a<< ", b = "<< b<< "\n";
cout<< "c = "<< c;
cout<< ", c squared = "<< square(c++)<< "\n";
cout<< "Now c = "<< c<< "\n";
return 0;
}
下面是該程序的輸出:
a = 25, b = 144
c = 13, c squared = 169
Now c = 14
輸出表明,內(nèi)聯(lián)函數(shù)和常規(guī)函數(shù)一樣,也是按值來(lái)傳遞參數(shù)的。如果參數(shù)為表達(dá)式,如4.5 + 7.5,則函數(shù)將傳遞表達(dá)式的值(這里為12)。這使得C++的內(nèi)聯(lián)功能遠(yuǎn)遠(yuǎn)勝過(guò)C語(yǔ)言的宏定義,請(qǐng)參見(jiàn)旁注“內(nèi)聯(lián)與宏”。
盡管程序沒(méi)有提供獨(dú)立的原型,但C++原型特性仍在起作用。這是因?yàn)樵诤瘮?shù)首次使用前出現(xiàn)的整個(gè)函數(shù)定義充當(dāng)了原型。這意味著可以給square()傳遞int或long值,將值傳遞給函數(shù)前,程序自動(dòng)將這個(gè)值強(qiáng)制轉(zhuǎn)換為double類型。
內(nèi)聯(lián)和宏
inline工具是C++新增的特性。C語(yǔ)言使用預(yù)處理器語(yǔ)句#define來(lái)提供宏——內(nèi)聯(lián)代碼的原始實(shí)現(xiàn)。例如,下面是一個(gè)計(jì)算平方的宏:
#define SQUARE(X) X*X
這并不是通過(guò)傳遞參數(shù)實(shí)現(xiàn)的,而是通過(guò)文本替換來(lái)實(shí)現(xiàn)的——X是“參數(shù)”的符號(hào)標(biāo)記。
a = SQUARE(5.0);?is replaced by a = 5.0 * 5.0;
b = SQUARE(4.5 + 7.5);?is replaced by b = 4.5 + 7.5 * 4.5 + 7.5;
d = SQUARE(c++);?is replaced by d = c++ * c++;
上述示例只有第一個(gè)能正常工作??梢酝ㄟ^(guò)使用括號(hào)來(lái)進(jìn)行改進(jìn):
#define SQUARE(X) ((X)*(X))
但仍然存在這樣的問(wèn)題,即宏不能按值傳遞。即使使用新的定義,SQUARE(C++)仍將c遞增兩次,但是程序清單8.1中的內(nèi)聯(lián)函數(shù)square()計(jì)算c的結(jié)果,傳遞它,以計(jì)算其平方值,然后將c遞增一次。
這里的目的不是演示如何編寫(xiě)C宏,而是要指出,如果使用C語(yǔ)言的宏執(zhí)行了類似函數(shù)的功能,應(yīng)考慮將它們轉(zhuǎn)換為C++內(nèi)聯(lián)函數(shù)。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧