本文将主要介绍const
关键字的使用。
首先,说一下const
是什么: const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。
然后,我们来看一下这四处声明:
const int a = 1; //code1
const int *p = &a; //code2
int * const p = &a; //code3
const int * const p = &a; //code4
下面就具体说一下这四行代码的作用与区别。
code1
最简单,即声明a初值为1,且为常量,其值不可更改;
code2
即将变量a的地址赋值给p,此时输出*p的值为1,而且若进行*p = 2
会报错,也就意味着p所指向的值(a的值)是不可更改的;
code3
因为const修饰的变量是p,同code1
,也就意味着p存储的值(变量a的地址,也就是p指向的地址)是不可更改的,若进行p = &b
会报错;
code4
综合code2 code3
即可得出结论,p指向的地址和p指向变量的值都是不可更改的。
指针和const
现在,我们再来看一下指针与const结合使用时的微妙之处。
首先通过一个题来引出这部分内容:
/*仅通过一行代码来使程序的最后输出为2018*/
const int a = 2017;
//此处填入一行代码
cout << a << endl;
刚看到这里,可能会用疑惑,前面不是刚说了a是const int类型,值不能修改吗?
其实,还是因为我们的理解不深入,说的其实是不可以直接对const类型的值进行修改,但数据就在内存中放着,难道我们就只能眼睛看着,而没有任何办法吗?当然不是,此刻,神奇的指针又该出场了,通过指针间接修改a的值。我们可以通过指针找到变量a的内存空间,在内存中对a的值进行修改。
即 *((int *)&a) = 2018;
,这样,就会在最终输出时输出2018。
因为上述代码用到了强制类型转化,所以在这里再说一下,C++是不允许将const类型转化为非const类型的,因为如果:
const int x = 10;
int *p = &x;
通过上面的讨论,我们已经知道到了x的值时const类型,不可被更改,然而将x的地址赋给p,却可以通过指针轻易的修改x的值,这就使得x的状态很荒谬。但要是必须这样做,只能通过强制类型转化来实现。
/*仅通过一行代码来使程序的最后输出为2018*/
const int a = 2017;
*((int *)&a) = 2018; //此处填入一行代码
cout << a << endl;
PS:如果数据类型本身并不是指针,则可以将const数据或非const数据的地址赋给指向const的指针,但只能将非const数据的地址赋给非const指针。