今天面试被问到const限定符用法,发现自己有好多没有完全理解的东西,抓紧看书恶补。
const限定符做什么用?
当程序员希望定义这样一种变量,它的值不能被改变,那我们就用const修饰它,被const修饰的变量一般存储于常量存储区。如 const int bufsize=256;这样定义的bufsize缓冲区大小就等于256,在程序运行期间谁都不可以改变bufsize的值,比如bufsize=512;这样做将会引发错误,所以const对象必须进行初始化。当然初始化时也可以用比较复杂的表达式。
const int a=get_size(); //正确
const int a=512*256; //正确
const int a; //错误没有进行初始化
const int a=b; //正确,用另一个int变量初始化const对象
如何让const定义变量作用于多个文件?
这里要聊一下const定义的变量只作用在本文件中,一个项目中有多个文件,如果多个文件定义了多个相同变量,那么编译器就为不同文件生成独立变量,如果想让const对象像其他对象一样工作,也就是只在一个文件中定义,多个文件都可以使用的话,就需要用到extern关键字:
//file1.cpp定义并初始化了常量bufsize,该常量能被其他文件访问
extern const int bufsize=fun();
//file1.h头文件
extern const int bufsize; //与file1.cpp中定义的bufsize时同一个
const的引用是怎么回事?
当我们把引用绑定到const对象上时,称之为对常量的引用。与普通引用不同,不能通过引用改变对象的值。
const int a=512;
const int &r=a; //正确:引用及其对应的对象都是常量
a=10; //错误,a是常量不可以直接修改
r=10;//错误,r是对常量的引用不可以修改
int &r=a; //错误,让一个非常量引用指向一个常量对象
int a=10; const int &b=a; //没错但是不能通过b改变a的值
指针和const关系是怎样的?
一.与引用一样,也可以令指针指向常量或非常量,我们称之为:指向常量的指针。
const double w=3.14; //w是一个双精度常量,它的值是不可以改变的
double *r=&w; //r是一个普通指针,不可以指向常量地址
const double *r=&w; //正确,r可以指向一个双精度常量,但是*r是不可以改变值的,它和double const *r是一样的,但是我们可以改变r指向的地址,但是*r的值不可以改变。
double a=3.14; const double *r=&a; //正确,允许常量指针指向非常量对象
二.常量指针
当我们把指针当作常量时,就叫做常量指针。常量指针必须进行初始化,因为一旦初始化完成那么它的值也就是存放在指针中的那个地址就不能改变了。
int a=0;
int *const c=&a; //c将一直指向a
const double w=3.14;
const double *const r=&w; //r是一个指向常量对象的常量指针
所以我总结出:
const int w=10;
1.指向常量的指针两种形式
const int *a=&w;
int const *a=&w;
两种形式是一个意思,即这是一个指向常量的指针,我们不可以通过*a修改常量的值,但是指针a不是常量,我们可以通过改变a的地址指向别的常量。
2.常量指针
int *const a=&w;
即指针a是一个常量,它一直指向w的地址,但是我们可以通过*a来改变w的值,但是我们不可以改变a指向的地址。
顶层const和底层const有什么区别?
顶层const表示指针本身是个常量,底层const表示指针指的对象是常量。
顶层const例子:
int i=0;
int *const p=&i; //不能改变p的值,这是一个顶层const
const int ci=0; //不能改变ci的值,这是一个顶层const
底层const例子:
const int *p=&ci; //允许改变p的值,这是一个底层const
int const *p=&ci; //同上
const int &r=i; //用于声明引用的const都是底层const
const int *const p=&ci; //靠右边的const是顶层const,靠左的const是底层const
对于两种const主要在拷贝对象时有区别,对于拷入考出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转换为常量,反之不行。
const int ci=0;
const int *const a=&ci;
int *p=a; //错误,a包含底层const的定义,而p没有
const int *p1=&ci;
p1=a; //正确,p1和a都是底层const
p1=&i; //正确,int*能转换成const int*
int &r=ci;//错误,普通的int&不能绑定到int常量上
const int &r2=i;//正确,const int&可以绑定到一个普通的int上