constexpr (C++)
關鍵字 constexpr
是在 C++11 中引進,並在 C++14 中改善。 這表示 const ant 運算式 。 如同 const
,它可以套用至變數:當任何程式碼嘗試將值修改 if 為 y 時,就會引發編譯器錯誤。 不同于 const
, constexpr
也可以套用至函式和類別 const Ructor。 constexpr
表示值或傳回值是 const ant,而且可能的話,會在編譯時期計算。
constexpr
只要需要整數, const 都可以使用整數,例如範本引數和陣列宣告。 而且,在編譯時間計算值而不是執行時間時,它可協助您的程式執行速度更快,且使用較少的記憶體。
若要限制編譯時間 const ant 計算的複雜度,以及它們對編譯時間的潛在影響,C++14 標準要求 ant 運算式中的 const 類型必須是 常值型別 。
語法
constexpr
literal-type ident if ier =const ant-expression;
constexpr
literal-type ident if ier { const ant-expression } ;
constexpr
literal-type ident if ier ( params ) ;
constexpr
ctor ( 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
。本文不能包含語句
goto
或try
區塊。非範本的
constexpr
明確特製化可以宣告為constexpr
:範本的
constexpr
明確特製化不一定是constexpr
:
下列規則適用于 constexpr
Visual Studio 2017 和更新版本中的函式:
它可能包含
if
和 語句,以及所有迴圈語句,包括for
、範圍型for
、while
和 do- while 。switch
它可能包含區域變數宣告,但必須初始化變數。 它必須是常數值型別,而且不能是
static
或執行緒區域。 本機宣告的變數不需要為const
,而且可能會變動。constexpr
static
非成員函式不需要隱含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 或更新版本。
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應