常量表达式
常量表达式是指值不会改变且在编译阶段就能得到计算结果的表达式:
const int max_files = 20; //是常量表达式 const int limit = max_file + 1; //是常量表达式 int staff_size = 27; //不是常量表达式 const int sz = get_size(); //不是常量表达式,尽管sz本身是一个常量,但是它的值直到程序运行时才能获得
constexpr(c++11)
c++11允许将变量声明为constexpr类型让编译器来验证变量是否为一个常量表达式。声明为constexpr的变量一定是一个常量,并且必须用常量表达式来初始化:
constexpr int mf = 20; constexpr int limit = mf + 1; constexpr int sz = get_size(); //只有当get_size()是一个constexpr函数时才是正确的声明
const变量 和 constexpr 变量之间的主要区别
1.const 变量的初始化可以延迟到运行时,而 constexpr 变量必须在编译时进行初始化:
const int sz = get_size(); //正确的声明,但是sz不是常量表达式 constexpr int sz = get_size(); //只有当get_size()是一个constexpr函数时才是正确的声明
2.constexpr声明中如果定义了一个指针,限定符constexpr只对指针有效,与指针所指的对象无关:
const int* p = nullptr; //p是一个指向整型常量的指针 constexpr int* q = nullptr; //q是一个指向整型的常量指针 constexpr const int* r = nullptr; //r是一个指向整型常量的常量指针
constexpr函数
用限定符constexpr修饰函数,使之用于常量表达式中,constexpr函数有这么几个特性:
1.函数的返回类型和所有的形参类型都是字面值类型
2.函数体中只有一条语句,而且只能是一条return语句(但其实也是可以包含其他语句的,只要这些语句在程序运行时不执行任何操作就行,如:空语句、类型别名、using声明)
constexpr int new_sz() { return 43; }
3.constexpr函数被隐式地指定为内联函数
4.编译器其实也允许constexpr函数的返回值和形参不是字面值:
constexpr int get_size(int a) { return a; } int main() { int size = 5; int y = get_size(size); //正确,因为y是非constexpr的,可以不要求get_size是constexpr的 constexpr int z = get_size(size); //错误!!! int arr1[get_size(5)]; //正确 int arr2[get_size(size)]; //错误,数组的大小要求是常量表达式 return 0; }
5.内联函数和constexpr函数可以在程序中多次定义,所以一般定义在头文件中:
你可以在a.h里定义
inline int fun()
{
return 1;
}
在 b.h里定义
inline int fun()
{
return 100;
}
因为inline函数编译时需要直接插入函数代码,所以不能使用extern,每个cpp源文件中必须包含其定义代码(不是声明) 所以"内联函数有可能在程序中定义不止一次,"就是指在每个调用inline函数的cpp源文件中都要有inline函数的定义,所以把inline函数定义在头文件中,需要时include就可以了;