一、常量表达式
常量表达式:是指
值不会改变
并且在编译过程就能得到计算结果
的表达式。
例如:
const int a = 10;//a就是一个常量表达式
const int b = a +1;//b也是一个常量表达式
int c = 0;//c不是常量表达式,c的值可以改变
const int sz = get_size();//不是常量表达式,因为get_size()函数需要在运行阶段才能得到结果
二、constexpr 变量
-
在一个复杂系统中,我们很难分辨一个一个初始值到底是不是常量表达式。我们可能认为只要定义了const的变量就是常量表达式了,但并不是这样的,就像上面那个第四个表达式就不是常量表达式。
-
C++11新标准规定,允许变量声明为
constexpr
类型以便编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:
constexpr int mf = 10;//10是常量表达式,所以mf也是常量表达式
constexpr int lm = mf+1;//mf+1是常量表达式
constexpr int sz = size();//size()不是常量表达式,所以sz 就不是常量表达式,就会报错。
如果你认定变量是一个常量表达式,那就把它声明成constexpr类型。
三、指针和constexpr
- 必须明确一点,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针本身有效,与指针所指向的对象无关。
const int *p = 10;//p是一个指向整型常量的指针,不可以修改p指向的值,但可以改变p的值来改变地址。
constexpr int *q = nullptr;//q是一个指向整型的常量指针,可以改变它所指向的值,但不可以改变其地址。
- 和其他常量指针类似,constexpr指针也可以指向常量也可以指向非常量,但有一个前提,
constexpr指针只能指向固定地址中,如果一个地址是在函数中那就不能指向它,变量地址必须定义函数外或者一类超出函数本身外还能有效的变量,这类变量超出函数体外还能拥有固定地址。
例如:
int i = 0;
constexpr int j = 10;
//i 和j 都必须声明在函数体之外
constexpr const int *p = &i;//正确
constexpr int * p1 = &j;//正确
//-------------------
//如果将变量声明在函数体内就会报错
int main()
{
int i = 0;
constexpr int *p = &i;//编译器会报错
return 0;
}