constexpr (C++)

關鍵字 constexpr 是在 C++11 中引進,並在 C++14 中改善。 這表示 const ant 運算式 。 如同 const ,它可以套用至變數:當任何程式碼嘗試將值修改 if 為 y 時,就會引發編譯器錯誤。 不同于 constconstexpr 也可以套用至函式和類別 const Ructor。 constexpr 表示值或傳回值是 const ant,而且可能的話,會在編譯時期計算。

constexpr只要需要整數, const 都可以使用整數,例如範本引數和陣列宣告。 而且,在編譯時間計算值而不是執行時間時,它可協助您的程式執行速度更快,且使用較少的記憶體。

若要限制編譯時間 const ant 計算的複雜度,以及它們對編譯時間的潛在影響,C++14 標準要求 ant 運算式中的 const 類型必須是 常值型別

語法

constexprliteral-type ident if ier =const ant-expression;
constexprliteral-type ident if ier { const ant-expression } ;
constexprliteral-type ident if ier params ;
constexprctor params );

參數

params
一或多個參數,每個參數都必須是常值型別,而且本身必須是 const ant 運算式。

傳回值

constexpr變數或函式必須傳回 常數值型別

constexpr 變數

constexpr 變數之間的 const 主要 d if 遞迴是變數的 const 初始化可以延後到執行時間。 constexpr變數必須在編譯時期初始化。 所有 constexpr 變數都是 const

  • 當變數具有常值型別且初始化時,可以使用 宣告 constexpr 變數。 如果初始化是由 ructor 所依據 for , const 則 ructor const 必須宣告為 constexpr

  • 當符合這兩個條件時,可能會宣告 constexpr 參考:參考的物件是由 const ant 運算式初始化,而且在初始化期間叫用的任何隱含轉換也是 const ant 運算式。

  • 變數或函式的所有宣告 constexpr 都必須具有 constexpr 規格 if ier。

constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression

constexpr 函式

constexpr 式是一個函式,其傳回值在編譯期間可計算,當取用程式碼需要它時。 取用程式碼需要在編譯階段傳回值來初始化 constexpr 變數,或提供非類型樣板引數。 當其引數為 constexpr 值時,函 constexpr 式會產生編譯時間 const ant。 當使用非 constexpr 引數呼叫,或在編譯時期不需要其值時,它會在執行時間產生值,例如一般函式。 (這種雙重行為可讓您不必撰寫 constexpr 和非 constexpr 版本的相同函式。

constexpr 式或 const ructor 是隱含的 inline

下列規則適用于 constexpr 函式:

  • constexpr 式必須接受並只 傳回常數值型別

  • constexpr 式可以是遞迴的。

  • 可以是 for e C++20、 constexpr 函式不可為 虛擬 ,而且 const 當封入類別具有任何虛擬基類時,無法將 ructor 定義為 constexpr 。 在 C++20 和更新版本中,函 constexpr 式可以是虛擬的。 當您指定 if y /std:c++20 或更新版本的編譯器選項時,Visual Studio 2019 16.10 版和更新版本支援 constexpr 虛擬函式。

  • 主體可以定義為 = default= delete

  • 本文不能包含語句 gototry 區塊。

  • 非範本的 constexpr 明確特製化可以宣告為 constexpr

  • 範本的 constexpr 明確特製化不一定是 constexpr

下列規則適用于 constexpr Visual Studio 2017 和更新版本中的函式:

  • 它可能包含 if 和 語句,以及所有迴圈語句,包括 for 、範圍型 forwhile do- whileswitch

  • 它可能包含區域變數宣告,但必須初始化變數。 它必須是常數值型別,而且不能是 static 或執行緒區域。 本機宣告的變數不需要為 const ,而且可能會變動。

  • constexprstatic 非成員函式不需要隱含 const

constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

提示

在 Visual Studio 偵錯工具中,偵錯非優化偵錯組建時,您可以藉由將中斷點放在編譯階段來判斷函式是否 constexpr 正在編譯階段進行評估。 如果叫用中斷點,便已在執行階段呼叫此函式。 否則便是在編譯時期呼叫函式。

Extern constexpr

/Zc:externConstexpr 編譯器選項會使編譯器將外部連結 套用 至使用 extern constexpr 所宣告的變數。 在舊版的 Visual Studio 中,預設或當 /Zc:externConstexpr- 是規格 if ied 時 ,即使使用 關鍵字,Visual Studio 仍會將內部連結套用至 constexpr 變數 extern 。 從 Visual Studio 2017 Update 15.6 開始,可以使用 /Zc:externConstexpr 選項,且預設為關閉。 /permissive- 選項不會啟用 /Zc:externConstexpr

範例

下列範例顯示 constexpr 變數、函式和使用者定義型別。 在 中的最後一個語句 main()constexpr ,成員函 GetValue() 式是執行時間呼叫,因為編譯時期不需要知道值。

// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>

using namespace std;

// Pass by value
constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp2(x * x, n / 2) :
        exp2(x * x, (n - 1) / 2) * x;
}

// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
    return N;
}

// Recursive constexpr function
constexpr int fac(int n)
{
    return n == 1 ? 1 : n * fac(n - 1);
}

// User-defined type
class Foo
{
public:
    constexpr explicit Foo(int i) : _i(i) {}
    constexpr int GetValue() const
    {
        return _i;
    }
private:
    int _i;
};

int main()
{
    // foo is const:
    constexpr Foo foo(5);
    // foo = Foo(6); //Error!

    // Compile time:
    constexpr float x = exp(5, 3);
    constexpr float y { exp(2, 5) };
    constexpr int val = foo.GetValue();
    constexpr int f5 = fac(5);
    const int nums[] { 1, 2, 3, 4 };
    const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };

    // Run time:
    cout << "The value of foo is " << foo.GetValue() << endl;
}

需求

Visual Studio 2015 或更新版本。

另請參閱

宣告和定義
const