2.4 const 限定符
const int k; //错误 K是一个未经初始化的常量
2.4.1 const的引用
把引用绑定到const 对象上,我们称之为对常量的引用,与普通引用不同的是,对常量的引用不能被工作修改它所绑定的对象。
const int ci = 1024;
const int &r1 = ci;
r1 = 42;
int &r2 = ci;//错误,试图让一个非常量引用指向一个常量对象
因为不允许直接为ci 复制,当然也就不能通过引用去改变ci。 因此,对r2的初初始化时错误的,假设该初始化合法,则可以通过r2来改变它引用对象的值,这显然是不正确的。
初始化和const的引用
引用的类型必须与引用对象的类型完全一致,但有两个例外:
a. 初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可,尤其,允许为一个常量引用绑定非常量的对象,字面值,甚至是个一般表达式。
对const的引用可能引用一个并非const的值
常量引用仅仅对可参与的 操作做出了限定,对于引用的对象本身是不是一个常量未做限定,因为对象也可能是个非常量,所以允许通过其他途径改变它的值:
int i = 42;
int &r1 = i;//引用ri 绑定对象i
const int &r2 =i; //r2也绑定对象i;但是不允许通过r2修改i的值
r1 = 0; //r1并非常量,i的值修改为0
r2 = 0; //错误,r2是一个常量引用
r2绑定非常量整数i是合法的行为,但是不允许通过r2修改i的值,但是i的值可以通过其它途径修改,既可以直接给i赋值,也可以通过向r1一样绑定到i的其它引用来修改。
2.4.2 指针和const
指向常量的指针不能用于改变其所指对象的值,要想存放常量对象的地址,只能使用只想常量的指针:
const double pi = 3.14; //pi是个常量,它的值不能改变
double *ptr = π //错误,ptr是一个普通指针
const double *cptr = π // 正确,cptr可以指向一个双精度常量
*cptr =42; //错误,不能给cptr赋值
double dval = 3.14 ;//dval 是一个双精度浮点数,它 的值可以改变
cptr = & dval;//正确,但是不能通过cptr改变dval的值.
const指针
指针是对象而引用不是,常量指针必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个值就不能再改变了)
把*放在const关键字之前,用以说明指针是一个常量,这样的书写形式隐含着一层意味,不便的是指针本身的值而不是指向的那个值。
int errNum = 0;
int *const curErr = &errNumb; //curErr 将一直指向errNum;
const double pi = 3.14159;
const double *const pip = π //pip是一个指向常量对象的常量指针
//指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指对象的类型,如pip 是一个指向常量的常量指针,则不论是pip还是pip自己存储的那个地址都不能改变。,相反,curErr指向的是一个一般非常量整数那么完全可以用curErr去修改errNumb的值:
*pip = 712; //错误,pip是一个指向常量的指针
if(*curErr){
*curErr = 0;//正确,把curErr 所指的对象的值重置。
}