2.4 const 限定符
关键字const : 值不能被改变 必须初始化
const int bufSize = 512; //输入缓冲区大小,将bufSize定义成了一个常量 bufSize = 512; //错误:试图向const对象写值 const int i = get_size(); //正确:运行时初始化 const int j = 42; //正确;编译时初始化 const int k; //错误:k是一个未经初始化的常量
int i = 42; const int ci = i; int j = ci; //用一个对象取初始化令一个对象,则它们是不是const无关紧要
默认状态下,const对象仅在文件内有效
如果想在多个文件间共享const对象,必须在变量的定义前添加extern关键字。
//file_1.cc定义并初始化了一个常量,该常量能被其他文件访问 extern const int bufSize = fun(); //file_1.h头文件 extern const int bufSize;//与file_1.cc中定义的bufSize是同一个
2.4.1 const的引用
把引用绑定到const对象上,对常量的引用不能被用作修改它所绑定的对象。
const int ci = 1024; const int &r1 = ci; r1 = 42; //错误。r1是对常量的引用。 int &r2 = ci; //错误。试图让一个非常量引用指向一个常量对象。
初始化和对const的引用
int i = 42; const int &r1 = i; const int &r2 = 42; const int &r3 = r1 * 2; int &r4 = r1 * 2; //F. r4是一个普通的非常量引用。 //初始化常量引用时允许用任意表达式作为初始值。
2.4.2 指针和const
类似于常量引用,指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。
const double pi = 3.14 double *ptr = π //F. ptr是一个普通指针 const double *cptr = π *cptr = 42; //F. 不能给*cptr赋值 //允许令一个指向常量的指针指向一个非常量。 double dval = 3.14; cptr = &dval; //T.但不能通过cptr改变dval的值。
const指针
指针是对象,允许把指针本身定为常量。常量指针必须初始化,且存放在指针中的地址(即指针的值)不能再改变。把*放在const关键字之前用以说明指针是一个常量。
int errNumb = 0; int *const curErr = &errNumb; //curErr将一直指向errNumb const double pi = 3.14; const double *const pip = π //pip是一个指向常量对象的常量指针
* 从右向左读 此例中,离curErr最近的是const,意味着curErr本身是一常量对象,对象的类型由声明符的其余部分确定。
2.4.3 顶层const
顶层const:指针本身是个常量。
底层const:指针所指对象是常量。
int i = 0; int *const p1 = &i; //不能改变p1的值,顶层const const int ci = 42; //不能改变ci的值,顶层const const int *p2 = &ci; //允许改变p2的值,底层const const int *const p3 = p2; //靠右顶层,靠左底层 const int &r = ci; //用于声明引用的const都是底层const //执行对象的拷贝操作时,顶层const不受什么影响 i = ci; //T 。ci是一个顶层const,对此操作无影响。 p2 = p3; //T 。 p2和p3指向的对象类型相同,p3顶层const部分无影响。
底层const的限制不能忽视。当执行对象的拷贝操作时,两个对象必须具有相同底层const资格,或者两个对象的数据类型必须能够转换。非常量可以转换为常量,反之不行。
int *p = p3; //F。p3包含底层const p2 = p3; //T 。 p2 = &i; //T 。int*能够转化为const int* int &r = ci; //F 。普通的int&不能绑定到int常量上 const int &r2 = i; //T 。const int& 可以绑定到一个普通int上
2.4.4 constexpr和常量表达式
常量表达式:值不会改变并且在编译过程就能得到计算结果的表达式。
const int max_files = 20; const int limit = max_files + 1; int staff_size = 27; //不是。 const int sz = get_size(); //不是。
constexpr变量
将变量声明为constexpr类型以便编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
constexpr int mf = 20; //20是常量表达式 constexpr int limit = mf + 1; //mf+1是常量表达式 constexpr int sz = size(); //只有当size是一个constexpr函数时才是一条正确的声明语句
一般来说,如果认定变量是一个常量表达式,就把它声明成constexpr类型。
指针和constexpr
一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。
const int *p = nullptr; //p是一个指向整型常量的指针 constexpr int *q = nullptr; //q是一个指向整数的常量指针,顶层
constexpr int *np = nullptr; //np是指向整形的常量指针,值为空 int j = 0; constexpr int i = 42; //i的类型是整形常量 //i和j都必须定义在函数体之外 constexpr const int *p = &i; //p是常量指针,指向整型常量i constexpr int *p1 = &j; //p1是常量指针,指向整数j
浙公网安备 33010602011771号