一个形如42的值被称为字面值常量。字面值常量的形式和值决定了常量的类型。例如0x42是16进制表示的整型常量。‘a‘是char型字面值。字
面值常量顾名思义由字面意思表示,是常量。字面值常量在程序中是直接表示的,整型直接写出大小,字符直接写出字符。一个字面值常量在编译时被直接解析为立
即数,编译器内部维护字面值常量的类型。
常量表达式是指在编译过程中,该表达式的值不会改变,且编译过程中可以立即得到结果的表达式。一部分const对象是常量表达式,由常量表达式初始化的
const对象也是常量表达式。常量表达式在程序运行时不会改变,即使一个程序多次启动或外部参数发生变化,该值也不会改变。编译器在编译时可能把常量表
达式直接替换为立即数,具体要看编译环境。一般来讲,字面值常量属于常量表达式。
C++中允许将变量声明为constexpr类型以使编译器在编译时检查该变量是否是常量表达式。声明为constexpr的变量一定是常量表达式。且初始化必须用常量表达式。
例如:
const int a = 12; a是常量表达式
const int b = a+1; b也是常量表达式
const int c = getsize(); c不是常量表达式,编译器编译时无法确知getsize()的执行结果。
constexpr int c = getsize(); 将会报错
字面值类型是指编译时就能得到结果的类型,具体包括算术类型、引用和指针。自定义类、IO类不属于该类型。字面值类型的对象有严格的要求,字面值类型是那
些具有常量表达式属性的对象的类型。例如:字面值常量是算术类型。对于引用和指针,其限定比较严格。不是所有的指针都是常量表达式。只有那些在编译时就确
定地址指向的指针才是常量表达式,引用同理。因此nullptr、NULL、指向固定地址的指针是字面值类型。那么,如何判断指针是否指向固定地址呢?
程序在内存中的组织形式是段,有堆栈段、数据段和代码段。对于数据指针指向数据,函数指针则指向某个代码。
对
于定义在函数体外的变量,其指针是constexpr的;此类变量要占用数据段,而程序运行时,代码段和数据段大小位置均不会改变,因此编译器可以确定地
址指向,是constexpr的。此外,函数内部定义的static静态变量,也会在数据区使用固定地址,因此指针也是constexpr的。对于定义在
函数内部的变量,由于要在栈中开辟内存空间,而栈的情况要看程序运行状态,因此这类变量没有确定的地址,其指针不是constexpr的。代码段不会改
变,函数指针也是constexpr的。