inline/constexpr function

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)的類定義在同一個頭文件中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,656評論 1 51
  • 一些情況下函數(shù)有個別形參不會被用到,此類形參通常不命名以表示在函數(shù)體內(nèi)不會使用它。但是即便是這樣,調(diào)用此函數(shù)的時候...
    修司敦閱讀 353評論 0 0
  • 面向?qū)ο?Object Oritented 基于對象(Object Based) vs. 面向?qū)ο?Object ...
    Royye閱讀 539評論 0 1
  • #1.定義抽象數(shù)據(jù)類型1.1 設(shè)計Sales_data類1.2 定義改進(jìn)的Sales_data類1.3 定義類相關(guān)...
    MrDecoder閱讀 471評論 0 0
  • 0.一些有用的概念 <0>: 自動對象:對于普通局部變量對應(yīng)的對象而言,當(dāng)函數(shù)的控制路徑經(jīng)過該變量定義語句時創(chuàng)建該...
    BrightHewei閱讀 286評論 0 1

友情鏈接更多精彩內(nèi)容