常量表达式:是指值不会改变并且在编译过程就能得到计算结果的表达式,一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定。
const int max_files = 20; //max_files是常量表达式
const int limit = max_files + 1; //limit是常量表达式
int staff_size = 27; //staff_size不是常量表达式
const int sz = get_size(); //sz不是常量表达式 尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以不是常量表达式
c++11新标准规定允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量而且必须用常量表达式初始化
constexpr int mf = 20; //20是常量表达式
constexpr int limit = mf + 1; //mf+1是常量表达式
constexpr int sz = size(); //只有当size是一个constexpr函数时才是一条正确的声明语句
字面值类型:算术类型、引用和指针都属于字面值类型,自定义类sales_item、IO库、string类型则不属于字面值类型,也就不能被定义成constexpr,尽管指针和引用都能定义成constexpr,但他们的初始值受到严格限制,一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象,函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量,如果定义于函数体之外的对象其地址固定不变,能用来初始化constexpr指针。
指针和constexpr:在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关
const int*p = nullptr; //p是一个指向整型常量的指针
constexpr int *q = nullptr; //q是一个指向整数的常量指针
constexpr函数:constexpr函数是指能用于常量表达式的函数,定义constexpr函数要遵循几项约定:函数的返回类型及所有
形参都得是字面值类型,而且函数体重必须有且只有一条return语句
constexpr int new_sz() { return 42; }
constexpr int foo = new_sz(); //正确 foo是一个常量表达式
把内联函数和constexpr函数放在头文件内:
和其他函数不一样,内联函数和constexpr函数可以在程序中多次定义,不过对于某个给定的内联函数或者constexpr
函数来说,它的多个定义必须完全一致,基于这个原因,内联函数和constexpr函数通常定义在头文件中
constexpr构造函数:
尽管构造函数不能是const的,但是字面值常量类的构造函数可以是constexpr函数,事实上一个字面值常量类必须至少提供一个constexpr构造函数,constexpr构造函数可以声明成 = default,否则constexpr构造函数就必须既符合构造函数的要求(意味着不能包含返回语句),又符合constexpr函数的要求(意味着它能拥有唯一可执行语句就是返回语句)综合这俩点可知,constexpr构造函数体一般来说应该是空的,constexpr构造函数必须初始化所有数据成员,初始值使用constexpr构造函数或者是一条常量表达式
class Debug
{
public:
constexpr Debug(bool b = TRUE) :hw(b), io(b), other(b) {}
constexpr Debug(bool h, bool i, bool o) : hw(b), io(i), other(o) {}
private:
bool hw;
bool io;
bool other;
};
空指针nullptr:可以利用nullptr来初始化指针,从而获得空指针
int* p1 = nullptr; //等价于int* p1=0;