C++14嚐鮮:constexpr函式(編譯期函式)
阿新 • • 發佈:2019-01-10
constexpr
constexpr是constant expression(常量表達式)的縮寫,它是C++11新引進的關鍵字。使用constexpr關鍵字可以宣告編譯期的變數和函式。
constexpr函式
要宣告constexpr函式(編譯期的函式),必須在函式宣告前新增constexpr關鍵字。
#include <iostream> using namespace std; // C++98/03 template<int N> struct Factorial { const static int value = N * Factorial<N - 1>::value; }; template<> struct Factorial<0> { const static int value = 1; }; // C++11 constexpr int factorial(int n) { return n == 0 ? 1 : n * factorial(n - 1); } // C++14 constexpr int factorial2(int n) { int result = 1; for (int i = 1; i <= n; ++i) result *= i; return result; } int main() { static_assert(Factorial<3>::value == 6, "error"); static_assert(factorial(3) == 6, "error"); static_assert(factorial2(3) == 6, "error"); int n = 3; cout << factorial(n) << factorial2(n) << endl; //66 }
程式碼說明:
- 以上程式碼演示瞭如何在編譯期計算3的階乘。
- 在C++11之前,在編譯期進行數值計算必須使用模板超程式設計技巧。具體來說我們通常需要定義一個內含編譯期常量value的類模板(也稱作元函式)。這個類模板的定義至少需要分成兩部分,分別用於處理一般情況和特殊情況。
程式碼示例中Factorial元函式的定義分為兩部分:
當模板引數大於0時,利用公式 N!=N*(N-1)! 遞迴呼叫自身來計算value的值。
當模板引數為0時,將value設為1這個特殊情況下的值。 - 在C++11之後,編譯期的數值計算可以通過使用constexpr宣告並定義編譯期函式來進行。相對於模板超程式設計,使用constexpr函式更貼近普通的C++程式,計算過程顯得更為直接,意圖也更明顯。
但在C++11中constexpr函式所受到的限制較多,比如函式體通常只有一句return語句,函式體內既不能宣告變數,也不能使用for語句之類的常規控制流語句。
如factorial函式所示,使用C++11在編譯期計算階乘仍然需要利用遞迴技巧。 - C++14解除了對constexpr函式的大部分限制。在C++14的constexpr函式體內我們既可以宣告變數,也可以使用goto和try之外大部分的控制流語句。
如factorial2函式所示,使用C++14在編譯期計算階乘只需利用for語句進行常規計算即可。 - 雖說constexpr函式所定義的是編譯期的函式,但實際上在執行期constexpr函式也能被呼叫。事實上,如果使用編譯期常量引數呼叫constexpr函式,我們就能夠在編譯期得到運算結果;而如果使用執行期變數引數呼叫constexpr函式,那麼在執行期我們同樣也能得到運算結果。
程式碼第32行所演示的是在執行期使用變數n呼叫constexpr函式的結果。
準確的說,constexpr函式是一種在編譯期和執行期都能被呼叫並執行的函式。出於constexpr函式的這個特點,在C++11之後進行數值計算時,無論在編譯期還是執行期我們都可以統一用一套程式碼來實現。編譯期和執行期在數值計算這點上得到了部分統一。