const关键字的使用场景是面试中最为常见的考察点之一,现在对const的使用进行一些总结

const关键字

我们定义一种变量,希望它的值不被改变,并且随时警惕程序一不小心改变这个值,为了满足这一要求,引入了const关键字

因为const对象一旦创建后其值不能发生变化,所以const对象必须初使化

const int i = get_size(); 正确

const int j = 42; 正确

const int k; 未初始化,错误

初始化和const

对象的类型决定了其上的操作,与非const类型所能参与的操作相比,const只能完成其中大部分,并不是所有操作都合适。主要限制是只能在const类型上执行不改变其内容的操作。不能改变const限定的值,但是可以进行赋值,拷贝

默认状态下,const对象仅在文件内有效

编译器将在编译过程中把用到该变量的地方都替换成对用的值。每个文件内的const 变量是独立的。

特殊情况,有些const的初始值不是一个常量表达式,但是确实有必要在文件见共享,也就是想要达到,在一个文件中定义const,在其他多个文件中声明并使用它。解决方法:对于const变量不管是声明还是定义都添加extern关键字,这样只需要定义一次就可以了:

// file_1.cc 定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufSize = fcn();
// file_1.h 头文件,注意这是头文件
extern const int bufSize; //与file_1.cc中定义的bufSize是同一个
//将在别的地方出行

如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字

const的引用

定义:把引用binding到const对象上,我们称之为对常量的引用。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象:

const int ci = 1024;
const int &r1 = ci;//正确:应用及其对应的对象都是常量

r1 = 42; //错误:r1是对常量的引用
int &r2 = ci; //错误:试图让一个非常量引用指向一个常量的对象

常量引用是对const的引用

初始化和对const的引用

引用的类型必须与其所引用对象的类型一致,但是有两个例外。

初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。允许一个常量引用绑定非常量的对象、字面值,甚至是一个表达式

int i = 42;
const int &r1 = i; //允许将const int& 绑定到一个普通int对象上
const int &r2 = 42; //正确:r2是对一个常量的引用 去掉const将会报
// 错,将42可以看作一个const
const int &r3 = r1 * 2; //正确:r3是一个常量引用
int &r4 = r1 * 2; //错误:r4是一个普通的非常量引用

左值引用不能指向右值,但是const的可以

解释:当一个常量引用被绑定到另外一种类型时到底发生了什么:

double dval = 3.14;
const int &ri = dval;
//正确

此处的ri引用了一个int整数,为了确保ri绑定一个整数,编译器将上述代码变成了如下形式:

const int temp = dval; //由双精度浮点数生成一个临时的整型变量
const int &ri = temp; //让ri绑定这个临时量,也就是指向的地址不一样了

临时量:当编译器需要一个空间来暂存表达式的求值结果临时创建的一个未命名的对象。

对const的引用可能引用一个并非const的对象

int i = 42; //这是一个非const对象
int &r1 = i; // 引用r1绑定对象i
const int &r2 = i; // r2也绑定对象i,但是不允许通过r2修改i的值,即使i是个非const
r1 = 0; //r1并非常量,i的值修改为0
r2 = 0; //错误:r2是一个常量引用

指针和const

与引用一样,也可以令指针指向常量或常量。指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针: