导语
const在算法竞赛中确实并不常用,但作为c++语法中的限定符,还是有很大的作用,并且由于c++语言的复杂性,当const和引用、指针在一起的时候,使用过程中难免出问题,容易混淆
初始化
const类型的对象只能执行不改变内容的操作,比如运算和判断,一般来说,const类型在创建时就需要初始化赋值,并且这个值不能被改变,当然const类型对象的初始化可以由常量、另一个const类型对象、另一个普通对象来初始化,举例如下
int a=1;
const int x=1;
const int y=x;
const int z=a;
//三者都可以运行,无语法错误
const的作用范围一般为整个文件,即文件与文件之间的const是不能共享的,如果需要共享,就需要对const不管是声明还是定义都添加extern关键字(只定义一次)
const和引用
C++中的引用可以绑定在const对象上,一般称之为常量引用(一个简称),对常量引用不能被用作修改其所对应的对象,简单来说,常量引用删除了“根据引用可以修改原对象”的性质,使用时只能作为单纯的替换,而不能修改,常量引用的初始化允许任意能够转换为对应引用类型的表达式进行赋值
还需要区分的是,常量引用实际上代表不能通过这个引用修改原对象,而原对象如果不是常量的话,本质上是可以修改的,举例如下
int x=1212;
const int &a=x;//正确,因为int可以转换成const int
a+=2;//错误,不能通过a修改x
x+=2;//正确,可以修改x
int &b=x;
b=0;//正确
const int &c=b;
c=0;//错误
const和指针
const指针的用法比较类似于引用,指向常量的指针不能修改所指对象的值,只能存一个地址,当然对象也没有规定一定是常量,并且这个指针也可以指向别的常量,单纯的不能进行修改而已,举例如下
int a=1,b=2;
const int *index=&a;
cout <<*index<<endl;//输出1
index=&b;//可以修改指向常量的指针的赋值
cout <<*index<<endl;//输出2
常量指针与指向常量的指针有很大差别,前者指的是指针本身是常量,即初始化之后指针指向的值是不能改变的,后者指的是指针指向了一个常量(不能通过指针修改),举例如下
int a=1,b=2;
int *const index=&a;
*index=2;//可以修改
index=b;//不能修改,index指向的对象不能改变
对于变量声明的定义,最好的阅读方法是从右往左读,而不是把类似"int*"看做一种单独的变量,以int * const index为例,先是const,代表index本身就是一个常量对象,下一个是*,代表index是指针,最后是int,整个读起来代表index是一个int型常量指针
顶层const和底层const
在上面概念的基础上,顶层const和底层const不过是换了一个说话,顶层const代表指针本身是一个常量,一般紧挨变量名,底层const代表指针所指的对象是一个常量,一般写在首部,当执行对象的拷贝时,顶层const和底层const之间的差别很大,举例如下
顶层const
和一般的变量拷贝一样
int a=1,b=2;
int *const index1=&a;
int *index2=index1;//正确
底层const
执行拷贝操作时,拷入和拷出的对象必须拥有相同的底层const资格,或者能进行转换
int a=1,b=2;
const int *index=&a;
int *p=index;//错误
const int *q=index;/正确
详细解释一下为什么第二个int *p=index是错误的:假设这行代码是正确的,那么意味着a可以通过p进行值的修改,但p是由index转换而来的,而index是const int*类型,不能转换成int*类型,显然i不能通过index对a进行值的修改,假设不成立
总结
const的语法还是有些复杂的,特别是顶层const和底层const的区别,这两者都能和指针、const、引用联系起来,自己弄清楚了顶层const和底层const的区别,这两者的区别在自己的本科阶段就没有弄清楚,现在算亡羊补牢为时未晚
参考文献
- 《C++ Primer中文版》(第五版)