(1)const的来由
定义一种变量,我们希望防止程序不小心改变变量的值。因此产生了const限定符。
(2)初始化
由于const对象一旦创建就不可以改变,所以const对象必须进行初始化;
只能在const类型的对象上执行不改变内容的操作,其中一种就是初始化。也就是说,即使拿一个const对象去初始化另一个const对象也完全没有问题,因为拷贝一个对象的值不会改变这个对象。
(3)有效范围
默认状态下,const对象仅在文件内有效
(4)指针和const
a.指向常量的指针
令指针指向常量或非常量,指针本身不能用于改变其所指对象的值。容易想到,必须使用指向常量的指针来存放常量对象的地址。如:
const int num = 624;
int *ptr = &num //错误,ptr是普通指针
const int *conPtr = num//正确,conPtr是指向常量的指针
*conPtr = 720;//错误,不能用于改变所指对象的值
特别地,虽然常量对象的地址必须使用指向常量的指针,但是指向常量的指针可以指向一个非常量对象。他们之间并非充要条件。值得注意的是,仍然不能通过指针来改变常量对象的值。
b.const指针
由于指针本身也属于一种对象,因此可以把指针定义为常量类型,也叫作常量指针。和普通数据类型相同,常量指针必须在声明的同时初始化,之后它所指向的地址就无法改变。如:
int num = 624;
int *const ptr = # //ptr是常量指针
这里和指向常量的指针作对比,对于常量指针,指针本身是不可以改变的(即指向一个地址后就不可改变),但是可以通过指针修改所指地址存的对象的值,这取决于所指对象的类型。对于上例,如果:
*ptr = 720;//可行,num不是常量类型
是完全可以的。
再来看一个例子:
const double pi = 3.14159;
const double *const p = &pi//p是指向常量的常量指针
判断const是修饰指针还是所指对象有一个办法,即从右向左判断。上例中,p的左边是const,说明是常量对象,再读一个是*,说明是常量指针;double前的const修饰说明所指对象是常量double类型。可以拿这个方法判断上面所举的例子。
(5)const的引用
将引用绑定到const对象上叫做对常量的引用。另一种说法是“常量引用”。但严格来说,由于引用本身不是一个对象,所以这种说法不严谨。和上文中的指针作对比就可以知道,因为指针是一个对象,所以存在“指向常量的指针”和“常量指针”两种不同的类型,而引用只有“对常量的引用”一种,只是人们习惯叫做“常量引用”而已,实际上是一样的。
理解常量引用需要注意以下两点:
A.常量对象的引用必须是常量引用。
const int bir = 624;
int &zz = bir;//错误。非常量引用绑定常量对象
const &smart = bir;//正确。常量引用绑定常量对象
B.常量引用可能绑定一个非const对象
int day = 720;
int &b = day;//正确,普通的引用
const Int &y = day;//正确,常量引用绑定非const对象
b = 624;//正确
y = 96;//错误,不可通过常量引用改变绑定对象的值
总之,学习常量引用可以和指向常量的指针对照起来,二者在很多时候是一致的。
(6)一些相关概念
顶层const:指针本身是个常量
底层const:指针所指对象是个常量
顶层const可以表示任意的对象是常量。底层const只存在于指针和引用等复合类型的基本类型上。用于声明引用的const都是底层const,因为引用本身不是类型,无法对它进行修饰。