Wiki
constexpr
Existing English translations were reused. 1 current source blocks remain in Simplified Chinese, without triggering paid translation.
1.What problem does this section solve?
Some computations already have known results at compile time, but if ordinary functions are used, they must wait until runtime to be computed—wasting CPU time. In addition, some scenarios (array sizes, template parameters, static_assert) must use compile-time constants, which ordinary variables cannot do.
constexpr Enable functions and variables to be evaluated atcompile timetransferring runtime overhead to compile time, and can also be used where "compile-time constants are required".
2.What is this feature?
constexprDeclaring a variable or function can be evaluated at compile time. Introduced starting from C++11, subsequent standards have continuously enhanced it.
| C++ versions | Support |
|---|---|
| C++11 | Simple constexpr functions (a single return statement), constexpr variables |
| C++14 | constexpr functions support multiple statements, loops |
| C++17 | constexpr lambda |
| C++20 | consteval(must be executed at compile time), stronger constexpr |
| C++23 | constexpr supports more of the standard library |
3.C++ Standard Edition
C++11 (each subsequent version includes enhancements)
4.Required header files
No additional header files are required.constexpr is a language keyword.
5.Basic syntax
// constexpr 变量:值在编译期确定
constexpr int size = 100;
// constexpr 函数:可以在编译期执行
constexpr int square(int n)
{
return n * n;
}
// constexpr 变量可以用编译期函数初始化
constexpr int val = square(5); // 编译期计算
// C++20 consteval:必须在编译期执行(不能运行时调用)
consteval int cube(int n)
{
return n * n * n;
}
6.const vs constexpr
| Aspect | const | constexpr |
|---|---|---|
| Meaning | Variable cannot be modified | Variable or function can be evaluated at compile time |
| Initialization | Can be initialized at runtime | Must be initialized at compile time |
| Function | Can only modify member functions | Function can be executed at compile time |
| Purpose | Prevent variables from being modified | Compile-time computation, improve efficiency |
| Example | const int x = get_value(); |
constexpr int x = 5 * 3; |
7.Differences between constexpr, consteval, and constinit
这三个词看起来都和"常量"有关,但解决的问题不同。初学时先掌握 constexpr,再理解 C++20 的 consteval 和 constinit。
| Keyword | Meaning | Typical Scenario |
|---|---|---|
constexpr |
Can be evaluated at compile time or called at runtime | General compile-time functions, constant expressions |
consteval |
Must be evaluated at compile time | Generate compile-time IDs, compile-time validation |
constinit |
Ensures static objects are initialized at compile time, but the object is not necessarily const | Avoid dynamic initialization order issues for global variables |
Distinguish in one sentence:constexpr leans toward "can it be computed",consteval leans toward "must be computed now",constinit leans toward "the initialization timing must be early".
8.Example code
8.1.Example 1: constexpr variables — must be determined at compile time
#include <iostream>
int main()
{
constexpr int size = 10; // 编译期常量
int arr[size]; // ✅ 可以用作数组大小
const int runtime_size = size; // const 可以用编译期常量初始化
int arr2[runtime_size]; // ✅ 也可以用作数组大小(因为初始化值是 constexpr)
int n = 5;
// constexpr int s2 = n; // ❌ n 是运行时变量,不能初始化 constexpr
const int s3 = n; // ✅ const 可以在运行时初始化
// int arr3[s3]; // ❌ s3 不是编译期常量,不能用作数组大小
std::cout << "size = " << size << "\n";
return 0;
}
Running result:
size = 10
8.2.Example 2: Based on Example 1, constexpr function
#include <iostream>
// constexpr 函数:编译期可执行
constexpr int factorial(int n)
{
int result = 1;
for (int i = 1; i <= n; ++i) // C++14 起支持循环
{
result *= i;
}
return result;
}
int main()
{
// 编译期计算:factorial(5) 在编译时就得到 120
constexpr int f5 = factorial(5);
std::cout << "factorial(5) = " << f5 << "\n";
// 也可运行时调用
int n;
std::cout << "Enter a number: ";
std::cin >> n;
std::cout << "factorial(" << n << ") = " << factorial(n) << "\n";
return 0;
}
Running result:
factorial(5) = 120
Enter a number: 4
factorial(4) = 24
8.3.Example 3: Based on Example 2, constexpr is used for templates and compile-time checks
#include <iostream>
// constexpr 函数:编译期判断是否为质数
constexpr bool is_prime(int n)
{
if (n <= 1) return false;
for (int i = 2; i * i <= n; ++i)
{
if (n % i == 0) return false;
}
return true;
}
// 编译期静态断言
static_assert(is_prime(2), "2 is prime");
static_assert(is_prime(7), "7 is prime");
static_assert(!is_prime(9), "9 is NOT prime");
// 编译期生成质数数组
constexpr int get_nth_prime(int n)
{
int count = 0;
int num = 1;
while (count < n)
{
++num;
if (is_prime(num))
{
++count;
}
}
return num;
}
int main()
{
constexpr int primes[] = {
get_nth_prime(1), // 2
get_nth_prime(2), // 3
get_nth_prime(3), // 5
get_nth_prime(4), // 7
get_nth_prime(5) // 11
};
std::cout << "First 5 primes: ";
for (int p : primes)
{
std::cout << p << " ";
}
std::cout << "\n";
return 0;
}
Running result:
First 5 primes: 2 3 5 7 11
8.4.Example 4: C++17 constexpr lambda
#include <iostream>
int main()
{
// constexpr lambda:编译期可调用
constexpr auto square = [](int x) constexpr {
return x * x;
};
constexpr int result = square(5); // 编译期计算
std::cout << "square(5) = " << result << "\n";
// constexpr lambda 也可运行时调用
int n = 7;
std::cout << "square(" << n << ") = " << square(n) << "\n";
return 0;
}
Running result:
square(5) = 25
square(7) = 49
8.5.Example 5: Building on Example 4, constexpr can be called at runtime, while consteval cannot.
#include <iostream>
constexpr int square(int x)
{
return x * x;
}
consteval int compile_time_square(int x)
{
return x * x;
}
int main()
{
constexpr int a = square(5); // 编译期计算
int n = 7;
int b = square(n); // 运行期调用,也允许
constexpr int c = compile_time_square(6); // 必须编译期计算
// int d = compile_time_square(n); // ❌ 编译错误:n 不是编译期常量
std::cout << "a = " << a << "\n";
std::cout << "b = " << b << "\n";
std::cout << "c = " << c << "\n";
return 0;
}
Running result:
a = 25
b = 49
c = 36
9.Operation result
See the "run results" for each example above.
10.Key syntax explanation in the example
| Example | What was discussed | Newly introduced syntax | Why it is written this way | Notes |
|---|---|---|---|---|
| Example 1 | constexpr vs const | constexpr int size = 10;array size |
constexpr must be initialized at compile time and can be used as an array size | const can be initialized at runtime and is not guaranteed to be at compile time |
| Example 2 | constexpr function | loops inside a constexpr function | the same function can be called at compile time or at runtime | when called at compile time, all arguments must also be compile-time constants |
| Example 3 | constexpr used for static_assert | static_assert() |
compile-time checking; if it fails, compilation fails immediately | the arguments of static_assert must be compile-time constants |
| Example 4 | constexpr lambda | constexpr auto f = [](int x) constexpr {...}; |
a lambda can also be evaluated at compile time | supported since C++17; both constexpr keywords must be written |
| Example 5 | constexpr vs consteval | consteval |
a consteval function can only be called at compile time | consteval is only available in C++20 |
11.Common Errors
Error 1: Assigning a runtime variable to constexpr
int n = 5;
constexpr int x = n; // ❌ n 不是编译期常量
Correct approach:const int x = n;(use const instead of constexpr).
Error 2: constexpr functions assume all cases can be evaluated at compile time
constexpr int divide(int a, int b)
{
return a / b; // 编译期 b=0 会导致编译错误
}
constexpr int x = divide(10, 0); // ❌ 编译错误!
Correct approach: when calling at compile time, pay attention to the validity of the arguments.
Error 3: Undefined behavior inside a constexpr function
constexpr int get(int* p)
{
return *p; // 编译期不能解引用空指针
}
constexpr int x = get(nullptr); // ❌ 编译错误!
Correct practice: avoid undefined behavior in constexpr functions.
Mistake 4: Assuming that constexpr functions are always executed at compile time
constexpr int square(int x) { return x * x; }
int n = 5;
int y = square(n); // ✅ 这是运行期调用,不是编译期调用
Correct approach: when forced compile-time evaluation is required, put the result into a constexpr variable, static_assert, or template parameter; starting from C++20, the consteval function can also be used.
12.Usage Recommendations
- Use constexpr wherever it can be expressed:Move runtime computation to compile time for better program performance.
- constexpr functions work both at compile time and runtime:There is no need to write two versions of the code.
- Use
static_assertfor compile-time checks:Combined with constexpr functions, it is very powerful. - constexpr is not a "faster" magic:For small functions, the compiler will optimize them anyway. But it is useful for scenarios such as constant tables and precomputation.
- Only consider consteval when "must be compile-time" is required:For ordinary utility functions, prefer writing constexpr, as it has fewer restrictions.
13.Summary
constexprVariables must be determined at compile time and can be used as array sizes, template parameters, etc.constexprFunctions can be executed at compile time (when all arguments are also constexpr).constexprFunctions can also be called at runtime;constevalonly then must they be called at compile time.constEmphasizes "non-modifiable",constexprEmphasizes "compile-time evaluation".- C++Since 17, lambdas can use
constexpr. static_assert+ constexpr functions = compile-time safety net.