1.內(nèi)聯(lián)函數(shù)能避免函數(shù)調(diào)用的開銷
將函數(shù)指定為內(nèi)聯(lián)函數(shù),通常就是將它在每個調(diào)用點上 “內(nèi)聯(lián)地”展開。假設(shè)我們把shorterString函數(shù)定義成內(nèi)聯(lián)函數(shù), 則如下調(diào)用:
cout << shorterString(s1, s2) << endl;
將在編譯過程中展開成類似千下面的形式:
cout << (sl.size() < s2.size() ? s1 : s2) << endl;
從而消除了shorterString函數(shù)的運行時開銷。
在shorterString函數(shù)的返回類型前面加上關(guān)鍵字inline, 這樣就可以將它聲明成內(nèi)聯(lián)函數(shù)了:
//內(nèi)聯(lián)版本:尋找兩個string對象中較短的那個
inline const string &
shorterString(const string &sl, const string &s2){
return sl.size() <= s2.size() ? sl : s2;
}
內(nèi)聯(lián)函數(shù)說明只是向編譯器發(fā)出的一個請求,編譯器可以選擇忽略這個請求。
2.constexpr 函數(shù)
constexpr函數(shù)Cconstexpr function)是指能用于常釐表達(dá)式的函數(shù)。定義constexpr函數(shù)的方法與其他函數(shù)類似,但是又如下幾項約束:
- 函數(shù)的返回類型及所有形參的類型都得是字面值類型;
- 函數(shù)體中必須有且只有一條return語句;
constexpr int new_sz () {
return 42;
}
constexpr int foo = new_sz () ; //正確: foo是一個常量表達(dá)式,在編譯過程中,constexpr 函數(shù)被隱式的指定為內(nèi)聯(lián)函數(shù)
我們把new_sz 定義成無參數(shù)的constexpr 函數(shù)。因為編譯器能在程序編譯時驗證new_sz函數(shù)返回的是常朵表達(dá)式, 所以可以用new_sz函數(shù)初始化constexpr類型的變量 foo。
執(zhí)行該初始化任務(wù)時, 編譯器把對constexpr函數(shù)的調(diào)用替換成其結(jié)果值。為了能在編譯過程中隨時展開, constexpr函數(shù)被隱式地指定為內(nèi)聯(lián)函數(shù)。
- constexpr函數(shù)體內(nèi)也可以包含其他語句,只要這些語句在運行時不執(zhí)行任何操作就行。例如,constexpr函數(shù)中可以有空語句、類型別名以及using聲明。
- constexpr函數(shù)的返回值并非一個常量:
//如果arg是常量表達(dá)式, 則scale(arg)也是常量表達(dá)式
constexpr size_t scale(size_t cnt) {
return new_sz() * cnt;
}
當(dāng)scale 的實參是常量表達(dá)式時, 它的返回值也是常量表達(dá)式; 反之則不然:
int arr[scale(2) ];//正確: scale(2)是常量表達(dá)式
int i = 2; // i不是常量表達(dá)式
int a2[scale(i)];//錯誤: scale(i)不是常量表達(dá)式
當(dāng)我們給scale函數(shù)傳入一個形如字面值2的常械表達(dá)式時, 它的返同類型也是常量表達(dá)式。此時, 編譯器用相應(yīng)的結(jié)果值替換對scale函數(shù)的調(diào)用。
如果我們用一個非常量表達(dá)式調(diào)用scale函數(shù), 比如int類型的對象i, 則返回值是一個非常量表達(dá)式。當(dāng)把scale函數(shù)用在需要常量表達(dá)式的上下文中時, 由編譯器負(fù)責(zé)檢查函數(shù)的結(jié)果是否符合要求。如果結(jié)果恰好不是常量表達(dá)式,編譯器將發(fā)出錯誤信息。
NOTE:constexpr 函數(shù)不一定返回常量表達(dá)式;
3.把內(nèi)聯(lián)函數(shù)和constexpr 函數(shù)放在頭文件內(nèi)
和其他函數(shù)不一樣, 內(nèi)聯(lián)函數(shù)和constexpr函數(shù)可以在程序中多次定義。畢竟, 編譯器要想展開函數(shù)僅有函數(shù)聲明是不夠的, 還需要函數(shù)的定義。不過, 對于某個給定的內(nèi)聯(lián)函數(shù)或者constexpr函數(shù)來說, 它的多個定義必須完全一致。基于這個原因, 內(nèi)聯(lián)函數(shù)和constexpr函數(shù)通常定義在頭文件中。
4.令成員作為內(nèi)聯(lián)函數(shù)
在類中, 常有一些規(guī)模較小的函數(shù)適合千被聲明成內(nèi)聯(lián)函數(shù)。定
義在類內(nèi)部的成員函數(shù)是自動inline的;可以在類的內(nèi)部把inline作為聲明的一部分顯式地聲明成員函數(shù), 同樣的,也能在類的外部用inline關(guān)鍵字修飾函數(shù)的定義:
/* 可以在函數(shù)的定義處指定inline */
inline Screen &Screen:::move(pos r, pos c){
pos row = r * width;
cursor = row + c ;
return *this;
}
/*在類的內(nèi)部聲明成inline*/
char Screen:: get (pos r, pos c) const{
pos row = r * width;
return contents[row + c);
};
雖然我們無須在聲明和定義的地方同時說明inline, 但這么做其實是合法的。不過,最好只在類外部定義的地方說明inline, 這樣可以使類更容易理解。
NOTE: 和我們在頭文件中定義inline函數(shù)的原因一樣,inline成員函數(shù)也應(yīng)該與相應(yīng)的類定義在同一個頭文件中。