一 常量表达式:


值不会改变,编译中就能得到计算结果的表达式。

自然包括字面值,用常量表达式初始化的const 对象。如:


const int a=24;//a是常量表达式

const int b=a+1;//b也是常量表达式

int c=8;//c不是,普通int而不是const int

const int len=get_size();//len不是,因为要具体值运行时方才获知


二 constexpr变量


在C++11标准中规定,允许将变量声明为constexpr类型,以便由编译器验证变量值是否是常量表达式。

声明为constexpr变量一定是一个常量,且必须由常量表达式初始化!


constexpr int a=24;//24作为常量表达式初始化

constexpr int b=a+1;//a+1也是常量表达式

constexpr int len=get_size();//只有当get_size()是constexpr函数时才正确!


特别区分:

const int *p=nullptr;//p是个指向整型常量的指针!

constexpr int *q=nullptr;//q是一个指向整数的常量指针!


注:函数体内定义的变量一般而言不存放在固定的地址中(局部变量),constexpr指针不能指向

这样的变量。当然,函数体外的变量(静态)地址固定,可用来初始化constexpr指针。另外,在函数体内

定义的但是有效范围超出体内的变量(static)也可用来被constexpr指向。如若在函数外有:


int a=0;

constexpr int b=24;

则在函数体内作:

constexpr const int *p=&a;//p是常量指针,指向整型常量a

constexpr int *p1=&b;//p1是常量指针,指向整型b


三 constexpr函数


该类函数能用于常量表达式,返回值和所有形参均是字面值类型,函数体内必须有且只有一条return语句。

注:此处的字面值类型并不是单指字面值之意,字面值类型包括了算数类型,引用,指针,枚举和某些有限制的类。


constexpr int func(){return 24;}

constexpr int num=func();//正确!!


允许constexpr函数返回值不是常量。如

constexpr int getNum(int i){return i*2;}


如果getNum(arg)中arg不是常量表达式,则getNum(arg)不是常量表达式如:

int a=20;

getNum(a);


如果getNum(arg)中arg是常量表达式,则getNum(arg)也是常量表达式如:

constexpr int a=20;

getNum(a);


四 内联函数与constexpr函数关系


将一些短小精悍的功能弄成一个函数,优点是可读性强,确保行为统一,修改容易,重复利用等;

缺点是一次函数调用意味着一系列工作,保存寄存器,返回时回复现场,甚至各种拷贝实参等。


若将函数返回类型前加 inline,

指定为内联,意味着它能在调用之处“内联地”展开即可,没有函数运行开销。


在执行初始化任务时,编译器对constexpr函数调用替换成结果值,为了能在编译中随时展开,

constexpr函数已经被隐式地指定为内联函数!


有内联函数定义可知,内联函数与其他函数不同,可多次定义,原因是:

编译器想展开函数仅仅靠函数声明是不够的,需要知道函数定义行为。


当然,对于给定的内联函数,多个定义必须完全一致,故可将其定义放置在头文件中。