constexpr(C++11 引入,C++14 擴展)指示值或函數返回值在編譯期可計算。比 const 更強:const 只保證運行時不修改,constexpr 保證編譯期確定。
constexpr int x = 42; // OK
constexpr double pi = 3.14159; // OK
constexpr int y = x + 1; // OK,依賴 constexpr
int z = 10;
constexpr int w = z + 1; // 錯誤!z 非 constexpr
// 字面值類型要求
struct Point { int x, y; };
constexpr Point p = {1, 2}; // C++14 支持聚合類型
// constexpr Point q = Point{1,2}; // C++11 需構造函數 constexpr
滿足條件時,調用結果為編譯期常量:
using、typedef、static_assert、單條返回語句(C++11)或簡單邏輯(C++14:允許局部變量、循環、條件分支)。// C++11 風格:遞歸實現
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n-1);
}
// C++14 風格:迭代更直觀
constexpr int factorial(int n) {
int res = 1;
for (int i = 2; i <= n; ++i) res *= i;
return res;
}
// 編譯期調用
constexpr int f5 = factorial(5); // 120
int arr[factorial(4)]; // 數組大小需編譯期常量
| 場景 | const | constexpr |
|---|---|---|
| 初始化時間 | 運行時或編譯期 | 必須編譯期 |
| 函數參數 | 可修改(非常量引用) | 隱含 const |
| 函數返回 | 運行時計算 | 編譯期可計算 |
| 指針語義 | const int* p:指向常量 | constexpr int* p:常量指針(指針本身不可改) |
const int* p1 = nullptr; // 非常量指針,指向常量 int
constexpr int* p2 = nullptr; // 常量指針,指向非常量 int
constexpr const int* p3 = nullptr; // 常量指針,指向常量 int
類若滿足:
constexpr 構造函數則該類為字面值類型,可定義 constexpr 對象。
class Complex {
double re, im;
public:
constexpr Complex(double r, double i) : re(r), im(i) {}
constexpr double real() const { return re; }
constexpr double imag() const { return im; }
};
constexpr Complex c(3.0, 4.0); // 編譯期構造
static_assert(c.real() == 3.0, "compile-time check");
template
constexpr size_t length(const T(&)[N]) { return N; }
constexpr int arr[] = {1,2,3,4};
constexpr int arr2[length(arr)*2] = {1,2,3,4,5,6,7,8}; // 編譯期計算長度
constexpr 是現代 C++ 編譯期計算的核心工具。const:constexpr 修飾指針本身,而非指向對象。