constexpr变量、constexpr函数和常量表达式
常量表达式: 值不会改变且在编译过程中就可得到结果
const int max = 20;//max是常量表达式 const int min = max-19;//min是常量表达式
constexpr用途:便于编译器验证变量是否为常量表达式
constexpr int max =20;//20是常量表达式 constexpr int min = max-19;//max-19是常量表达式 constexpr int sz =size();//仅仅当size()是一个costexpr函数时正确
constexpr函数:
返回值类型及形参类型必须是字面量类型,且必须有且只有一个return语句
。
constexpr int fun()//constexpr函数,编译时验证返回值是constexpr { return 42; } constexpr int result = fun();//正确,把fun是一个常量表达式
constexpr函数体内部不能有其他语句,只能有类型别名,using声明。只不过在运行时,不执行任何操作。
constexpr函数可以返回非常量
constexpr scale(int i){return 100*i;} int arr[scale(2)];//正确,scale(2)是常量表达式 int j =100; int a2[sacle(j)];//错误,scale(j)不是常量表达式
如上例,当传入字面值2时,返回类型也是常量表达式,此时,编译器直接替换。但是使用非常量表达式,则返回值是一个非常量表达式,此时将其赋值给需要常量表达式的上下文中,编译器报错。
因为constexpr函数在编译阶段就已经替换,此时如果只将声明放入头文件中而没有定义是不够的,所以一般将内联函数和constexpr函数放到头文件中。
指针和constexpr
const int *p = nullptr; constexpr int *q = nullptr;//等同于 int* const q; int j =0; constexpr int i = 100; constexpr const int*p =&i;//i不能是函数体之内 必须加上const constexpr int* p =&j;
指针和引用都可以定义成constexpr,但是初始值受到限制,必须是nullptr或者0,或者是固定地址的对象
注意: 1. 函数体内的局部变量没有固定地址,所以constexpr指针不能指向他们
2. 函数体内的静态变量具有固定地址,是可以使得constexpr绑定