const
初始化
- const对象一旦创建后其值就不能再改变,所以const对象必须初始化
- 只能在const类型的对象上执行不改变其内容的操作
默认状态下 const对象仅在文件内有效
如果想在多个文件之间共享const对象,必须在变量的定义前添加extern关键字
//file_1.cc 定义并初始化一个变量,改变量能被其他文件访问 extern const int bufSize = fcn(); //file_1.h extern const int bufSize; //同一个
引用
常量引用是对const的引用
初始化常量引用时允许用任意表达式做为初始值,只要该表达式的结果能转换成引用类型即可
//常量引用被绑定到另外一个类型 double dval = 3.14; const int &ri = dval; //编译器把上述代码变成如下形式 const int temp = dval; const int &ri = temp; //这种情况下ri绑定了一个临时量对象,当ri不是常量时,改变ri只会影响temp对象
常量引用可能引用一个并非const的对象,常量引用仅对引用可参与的操作做出了限定,对引用的对象本身是不是一个常量未做限定
int i = 42; const int &r1 = i; //可以通过其他途径改变i
指针
要想存放常量对象的地址,只能使用指向常量的指针
const double pi = 3.14; const double *ptr = π
指向常量的指针没有规定其所指对象必须是一个常量,仅仅要求不能通过该指针改变其所指对象的值,没有规定不能通过其他途径改变
const指针
指针是对象而引用不是,允许把指针本身定为常量,常量指针必须初始化,一旦初始化完成,它的值(存放在指针中的地址)就不能再改变
*const 隐含说明不变的是指针本身的值而不是指向的值
// 1 int num = 0; int *const ptrNum = # /*指向非常量的常量指针,ptrNum将会一直指向num不能改变,但是可以改变其所指对象的值*/ *ptrNum = 1; // 2 const double pi = 3.14159; const double *const ptrPi = π /*指向常量的常量指针,不论是其所存对象的地址还是所指对象的值都不可以改变*/
顶层const
顶层const:表示指针本身是个常量,可以表示任意的对象是常量
底层const:表示指针所指的对象是一个常量,与指针和引用等复合类型的基本类型部分有关
int i = 0; int *const p1 = &i; //顶层const const int ci = 42; //顶层const const int *p2 = &ci; //底层const const int *const p3 = p2; //靠右的const是顶层,靠左的const是底层 const int &r = ci; //用于声明引用的const都是底层const
拷贝时底层const不受什么影响,但是执行拷贝的对象必须具有相同的底层const,一般来说非常量可以转换成常量,反之则不行
int *p = p3; //错误,p3包含顶层const定义,而p没有 p2 = p3; p2 = &i; // int* 可以转换成 const int* int &r = ci; //错误,普通的 int& 不能绑定到 int 常量上 const int &r2 = i; //const int& 可以绑定到一个普通的 int 上
constexpr和常量表达式
常量表达式 是指值不会改变并且在编译过程就能得到计算结果的表达式
const int max_size = 20; const int limit = max_size + 7 ; int staff_size = 27; // staff_size 不是常量表达式 const int sz = get_size(); // sz是一个常量,但是具体值得等到运行时才能获得,所以也不是常量表达式
constexpr变量 c++11允许将变量声明为constexpr类型一遍由编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化
constexpr int mf = 20; constexpr int limit = mf + 1; constexpr int sz = size(); //只有当size是一个constexpr函数时才正确
字面值类型 算术类型、枚举、引用和指针都属于字面值类型,自定义类、IO库、string类型不属于,一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象,定义于函数体之外的对象其地址固定不变,能用来初始化constexpr指针,一般函数体内的变量的地址不是固定不变的,但允许函数定义一类有效范围超出函数本身的变量(局部静态对象),其地址也是固定不变的
指针和constexpr constexpr把他所定义的对象置为了顶层const
constexpr int *q = nullptr; //q是一个指向整数的常量指针 const int *p = nullptr; //p是一个指向整型常量的指针