- constexpr關鍵字,用來定義常量表達式,用此關鍵字修飾的函數可以在程式編譯階段運作。
- inline是修飾内聯函數的,進而提高程式調用簡單函數的速度,在編譯器編譯的時候就可以替換對應的編譯表達式
需要注意的是,inline函數中不能包含if,swatch等分支語句,也不能進行異常接口聲明
内聯函數
下面的例子中:
// find longer of two strings
const string &shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}
為這樣的小操作定義一個函數的好處是:
閱讀和了解函數 shorterString 的調用,要比讀一條用等價的條件表達式取代函數調用表達式并解釋它的含義要容易得多。
如果需要做任何修改, 修改函數要比找出并修改每一處等價表達式容易得多。
使用函數可以確定統一的行為,每個測試都保證以相同的方式實作。
函數可以重用,不必為其他應用重寫代碼。
但是,将 shorterString 寫成函數有一個潛在的缺點:調用函數比求解等價表達式要慢得多。在大多數的機器上,調用函數都要做很多工作;調用前要先儲存寄存器,并在傳回時恢複;複制實參;程式還必須轉向一個新位置執行。
inline 函數避免函數調用的開銷
将函數指定為 inline 函數, (通常)就是将它在程式中每個調用點上“内聯地”展開。假設我們将 shorterString 定義為内聯函數,則調用:
cout << shorterString(s1, s2) << endl;
在編譯時将展開為:
cout << (s1.size() < s2.size() ? s1 : s2)<< endl;
進而消除了把 shorterString 寫成函數的額外執行開銷。
// inline version: find longer of two strings
inline const string & shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}
inline 說明對于編譯器來說隻是一個建議,編譯器可以選擇忽略這個。
一般來說,内聯機制适用于優化小的、隻有幾行的而且經常被調用的函數。大多數的編譯器都不支援遞歸函數的内聯。一個 1200 行的函數也不太可能在調用點内聯展開。
constexpr函數
constexpr函數是指用于常量表達式的函數。定義constexpr函數時需要注意:函數的傳回類型以及所有形參的類型都得是字面值類型,而且函數體中必須有且僅有一條return語句。
constexpr int new_sz(){return 42;}
constexpr int foo=new_sz();
把new_sz定義成無參數的constexpr函數,因為編譯器能在程式編譯時驗證new_sz函數傳回的是常量表達式,是以可用new_sz函數初始化constexpr類型的變量foo。
執行該初始化任務時,編譯器把對constexpr函數的調用替換成其結果值,為了能在編譯過程中随時展開,constexpr函數被隐式地指定為内聯函數。
Constexpr函數體内也可以有其他語句,但是這些語句必須保證在運作時不執行任何操作。例如:空語句,類型别名,以及using聲明。
允許constexpr函數傳回值并非常量:
constexpr size_t scale(size_t cnt){return new_sz()*cnt;}
當scale的實參是常量表達式時,它的傳回值也是常量表達式,反之則不然:
int arr[scale(2)]; // 正确,scale(2)是常量表達式
int i=2;
int a2[scale(i)]; //錯誤,scale(i)不是常量表達式
把 inline 函數和constexpr放入頭檔案
内聯函數和constexpr函數應該在頭檔案中定義,這一點不同于其他函數。畢竟編譯器能夠在調用點展開該函數的代碼。此時,僅有函數原型是不夠的。
不過,對于某個給定的内聯函數或者constexpr函數來說,它的多個定義必須一緻,基于這個原因,内聯函數和constexpr函數通常定義在頭檔案中。
參考:https://blog.csdn.net/susser43/article/details/44904073
https://www.cnblogs.com/xiaojianliu/articles/8979945.html#_label1