例如,const int a = 10;,这里的a是一个常量表达式,因为它是一个const(常量)修饰的整数,其值在编译时就已经确定为 10。再比如constexpr int b = 2 * 3;,b也是常量表达式,编译器在编译阶段就能计算出2 * 3的值为 6。
在 C++ 中,常量表达式是指在编译期间就能计算出结果的表达式。它的值在程序运行过程中是固定不变的。常量表达式可以是一个常量(如整数常量、字符常量等),也可以是由常量和运算符组成的表达式,只要这个表达式的值在编译时能够确定。
用途
数组大小定义:可以用于定义数组的大小。在 C++ 中,数组的大小必须是一个常量表达式。例如,const int size = 10; int array[size];,这里size是一个常量表达式,它确定了数组array的大小为 10。这有助于在编译时就分配好合适的内存空间,并且保证数组大小不会在运行时被意外修改。
模板参数:在模板编程中,常量表达式可以作为模板参数。例如,template <int N> struct Array{ int data[N]; }; constexpr int size = 5; Array<size> myArray;,这里size作为模板参数传递给Array模板,用于在编译时确定myArray内部数组data的大小。
枚举值初始化:用于初始化枚举类型的值。例如,enum class Color{ RED = 0, GREEN = 1, BLUE = 2 };,这里枚举值RED、GREEN和BLUE是常量表达式,它们在编译时就确定了对应的整数值,并且这些值在程序运行过程中是固定不变的。
在 C++ 中,一个比较直观的方法是尝试用constexpr关键字来声明这个表达式。如果一个表达式能够用constexpr成功声明,那么它大概率是一个常量表达式。例如,constexpr int a = 5 + 3;是合法的,这说明5 + 3是一个常量表达式。但是,如果有类似int x = 10; constexpr int b = x + 2;这样的代码,就会报错,因为x是一个变量,其值在编译时不确定,所以x + 2不是常量表达式。
检查编译时求值的可能性
考虑表达式中的各个元素。如果表达式中只包含常量(如字面常量、const修饰的变量,其初始值是常量表达式)和允许在编译时求值的运算符(如算术运算符+、-、*、/,位运算符&、|、^等),那么这个表达式有可能是常量表达式。但是,如果表达式中包含函数调用(非constexpr函数)、对象的动态分配(如new操作符)等在编译时无法确定结果的操作,那么这个表达式就不是常量表达式。例如,const int c = 7; constexpr int d = c * 2;是可以的,因为c是const修饰的常量,c * 2可以在编译时计算。而int* ptr = new int; constexpr int e = *ptr;是错误的,因为new操作在运行时分配内存,*ptr的值在编译时无法确定。