C++中const 详解

来源:互联网 发布:云存储软件 编辑:程序博客网 时间:2024/06/08 13:50

知识的学习在于对细节的深入理解,范范略知,时间一长也就不了了之了。这也是我写博客的初衷。

废话不说,我们还是从一道面试题说起:

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 = &num;
声明指出,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成员变量。

先总结如上,有错误还请大家指教!


0 0