一:概述
constexpr
是 C++11 引入的关键字,用于在编译时评估表达式并生成常量值。这可以提高性能和代码的可读性,减少运行时计算。
二:举例
1. 编译时常量表达式
constexpr
的主要用途是确保某些表达式在编译时计算。例如,数学计算、常量初始化等场景下,可以用constexpr
代替const
来强制在编译时执行计算
constexpr int square(int x) {
return x * x;
}
constexpr int result = square(5); // 编译时计算 result 的值为 25
2. 常量成员函数
当类的某些成员函数可以在编译时计算时,可以将其声明为constexpr
。在这样的函数中,只要输入是编译时常量,返回值也会在编译时确定。
struct Point {
int x, y;
constexpr Point(int xVal, int yVal) : x(xVal), y(yVal) {}
constexpr int getX() const { return x; }
constexpr int getY() const { return y; }
};
constexpr Point p(1, 2);
constexpr int x = p.getX(); // 在编译时计算
3. 如果需要在编译时确定数组的大小,可以使用constexpr
来计算数组的大小。
constexpr int getSize() {
return 10;
}
int arr[getSize()]; // 数组大小在编译时确定
4. constexpr
函数支持递归
这使得复杂的计算也可以在编译时完成。注意,递归的深度不能超出编译器的限制。
constexpr int factorial(int n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}
constexpr int result = factorial(5); // 编译时计算 result 为 120
三: 注意事项
1. 函数体限制:
在 C++11 中,constexpr
函数的函数体必须是单一的 return
语句,C++14 以后可以包含更多复杂的语句,比如条件判断、循环等。下面是 C++11 和 C++14 对函数体的不同要求:
// C++11 constexpr 函数(单个return语句)
constexpr int add(int a, int b) {
return a + b;
}
// C++14 constexpr 函数(可以包含条件判断)
constexpr int max(int a, int b) {
if (a > b) return a;
else return b;
}
2. 局限性:
constexpr
函数不能包含运行时只能执行的操作,例如:
- 不能抛出异常
- 不能使用
new
或动态内存分配 - 不能有运行时依赖的函数调用
3. 编译时和运行时调用:
constexpr
函数可以在编译时和运行时调用。如果参数是常量表达式,编译器会在编译时计算结果;如果参数不是常量表达式,函数会在运行时执行.
constexpr int sum(int a, int b) {
return a + b;
}
int x = 5;
int result1 = sum(3, 4); // 编译时计算
int result2 = sum(x, 4); // 运行时计算
4. 构造函数中的constexpr
:
从C++11开始,类的构造函数可以声明为constexpr
。这意味着可以使用constexpr
构造常量对象,前提是所有成员变量的初始化也是常量表达式。
5. constexpr
vs const
:
constexpr
确保编译时计算,而const
表示常量但不保证编译时计算。const
对象可以在运行时初始化,而constexpr
对象必须在编译时初始化。