C++ constexpr 常量表达式

it2025-12-20  12

概括

在C++11中引入了 constexpr 关键字. 意思是常量表达式, 详细来说就是在编译期可求值的表达式. 可以修饰表达式, 函数, 构造函数, 类等… 可以让编译器做出尺度更大的优化.


常量表达式的概念

这个关键字是为了解决以前的 const 关键字带来的一些问题, 其实在代码实战中 const 显然是只有readonly只读这个概念, 其在很多场合上并不符合逻辑常量这个概念, 就比如说:

const int f(){ return 1; } int main(){ int arr[f()]; return 0; } // 会报错

上述这个代码, 我们会得到报错: 函数调用在常量表达式中必须具有常量值 和 表达式的计算结果不是常数 . 然而在逻辑上, 上面这个函数返回的明显是一个逻辑上的常量.

常量表达式函数 而在使用了constexpr之后, 编译器就会大胆地对f()进行优化, 比如说直接内联了它, 而不需要等到运行时候才去计算

constexpr int f(){ return 1; } int main(){ int arr[f()]; return 0; } //可以通过

但是编译器并不会因为你告诉它某个函数或者某个表达式是常量表达式之后, 就一定会百分百信任你. 常量表达式函数只有当整个函数都是常量表达式的时候, 那么它才会在编译时确定返回值.

该函数的实参必须为常量表达式一般来说只能有一条return语句(C++14已经放宽了很多, 只要函数体的东西都是字面值就行), 三目运算符或者递归都是可行的函数不能为void返回值函数在使用前必须要有定义 (而不仅仅是声明)

其他情况下的, 即使使用了关键字修饰, 其会变成普通函数,编译器识别到之后该报错的还是会报错的.

constexpr int f(int x) { return x+1; } int main() { int a; cin >> a; int arr1[f(1)]; //ok int arr2[f(a)]; //error return 0; }

总的来说, constexpr 给了程序非常好的约束条件, 比如把函数形参设定为一定要常量表达式, 这样可以减少运行时候的开销, 对比宏定义来说的话更加安全可靠.


其他

constexpr类 把该类必须至少有一个constexpr修饰的构造函数

成员变量只能通过初始化列表来初始化, 函数体必须为空产生的对象中所有成员都会是constexpr, 也就是说该对象也是constexpr对象 class Point { public: int x, y; constexpr Point(int _x, int _y) : x(_x), y(_y) {} //初始化列表和空的函数体 constexpr Point() : Point(0, 0) {} }; int main() { constexpr Point p(666, 233); //常量表达式类 int arr[p.x]; return 0; }

const和constexpr同时使用 一般情况下, constexpr已经包含了const的语义, 因此没有必要同时使用, 但是也有特殊情况:

static constexpr int N = 3; int main() { constexpr const int *NP = &N; return 0; }

因为N是一个常量, 但是你不能用一个普通指针去指向一个常量, 因此你只能用一个const指针去指向.

最新回复(0)