知识的学习在于对细节的深入理解,范范略知,时间一长也就不了了之了。这也是我写博客的初衷。
废话不说,我们还是从一道面试题说起:
int main()
{
inti=10;
intj=1;
constint *p1;//(1)
intconst *p2=&i; //(2)
p2=&j;//(3)
int*constp3=&i;//(4)
*p3=20;//(5)
*p2=30;//(6)
p3=&j;//(7)
return0;
}</span>
指出上面程序错误的编号,请大家好好思考。。。。。
(1)是正确的,声明了一个指向常量的指针p1。
(2)是正确的,同样是声明了一个指向常量的指针p2,并且进行了初始化。
(3)是正确的,p2指针可以修改。
(4)是正确的,声明了一个指向int的常量指针p3。
(5)是正确的,p3所指向的值可以修改。
(6)是错误的,p2指向的常量不可以修改。
(7)是错误的,p3是一个常量指针,不可以修改。
所以答案是6,7.跟大家想的有没有出入,如果有,那么就接着往下看。我主要从4个方面来详细介绍const的使用方法和注意事项,const和变量,const和指针,const和函数,const和对象成员变量。
- const和变量
const和普通成员变量的使用方法很简单,如下:
const int num = 1;// 如果不进行初始化,会提示错误“常量 变量num 需要初始值设定项”</span>
用const来修饰普通变量,会改变变量的访问权限,变成只读,所以必须在声明的时候进行初始化。我们强调的只有这一点吗,真相远比想象的复杂!!!因为这里还有一个常量折叠的概念,常量折叠:在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表,可以算作一种编译优化,但是变量的名称是有效范围内还是可用的,并且在编译的时候从常量表中的直接替换,并不涉及到该变量的内存地址。我们还是从一道题目入手:
const int a = 10;// 这这里声明的变量a 就会产生常量重叠。
int *p = (int *)&a;
*p = 20;
cout << "a= " << a << endl << "p= " << *p;
return 0; </span>
那么大家思考具体会打印出什么值?详细讲解请大家点击链接。
- const和指针
如一开始的题目中所示,const和指针的使用情况略复杂,那么const和指针是如何结合的,总结有以下一种情况:
const int *point;
int const *point;
int * const point;
1.const int *point,指向常量的指针,防止通过该指针来修改所指向的值。
int num = 3;
const int *point = #
声明指出,point指向一个const int的值,并且不能通过point指针来修改这个值:
*point++;//是不允许的
然后大家注意:point指向的值并不一定是const int 类型的,就同上面的声明一样,我们可以修改num的值,所以point指向的const int的常量只是针对point而言的。而且point本身是可以改变的:
int num2 = 2;
point = &num2;// 是允许的
cout<<*point;// 输出 2
理解了上面这种情况后,以下几种情况就容易理解了:
2. int const * point,和第一种情况完全一致,经常拿来迷惑你。
3. int * const point,指针本身是常量,防止改变指针指向的位置。
int num3 = 1;
int *const point = &num3;// point 是一个常量指针,所以声明的时候必须初始化
*point++;// 指向的值可以修改
point++;// 会出错!!!
从程序中大家也就很清楚这几种使用方式的区别和容易出错的地方。
- const和函数(摘自C++primer plus 第六版)
1.这样可以避免由于无意间修改数据而导致的编程错误。
2.使用const使得函数能够处理const和非const实参,否则只能接受非const数据。
- const和对象成员变量
单独把它列出来是提醒大家,如果定义的对象
中有const修饰的
成员变量,则必须在初始化列表中进行初始化,因为必须先于对象初始化之前初始化const成员变量。
先总结如上,有错误还请大家指教!