我觉得遇到这种题,从“结合律”的角度来看就很好理解,先看两个简单的,比如:const int a  和 int const a

  1. const int a里的const和int结合,是一个意思是一个整型的常量,a作为一个整型常量,是不能改变的;
  2. 再看 int const a,const和a结合,意思也是 a是一个常量,不能被改变。综上所述,const int a  和 int const a作用是一样的。

也可以总结出一个复杂的结论:const放在类型符号 前 / 后 作用是一样的。

然后我们来看const int* p, int const* p以及int *const p。 继续使用“结合律”:

  1. const int* p,const和int结合在一起,意思是p指向一个整型常量,换句话说就是不能通过指针p改变p所指向的那块内存里的东西,因为它是一个常量,举个栗子就是,如果这样的p指向A,我们不能通过p改变A,但是我们可以让p不指向A,而指向别的B C D  E F G等等。
  2. int const* p,const和*p结合在一起,意思也是p指向一个常量,换句话说就是不能通过指针p改变p所指向的那块内存里的东西,因为它是一个常量,这样写和1里const int *p那样写最终效果是一样的,不能理解的话你可以向上看看我加黑的字体——const放在类型符号 前 / 后 作用是一样的。
  3. int *const p,const和p结合在一起,意思是p这个指针本身是一个常量,不能改变指针本身,但可以改变指针指向的那块内存里的数据,通俗地说就是,如果p是指向变量A的,你不能将p改为指向B,但是p指向的内容A却是可以修改的。

我们再来看一个栗子,

  1. const int * const p,const和p结合,p这个指针自身是一个常量,p如果指向A的话,那么就不能将p改为指向B了;
  2. 再看另一个const,它和int结合在一起,也就是p指向的东西是一个常量,不能通过指针p改变p所指向的那块内存里的数据。

So,你明白了吗?

下面要补充一点东西,如果你理解我上面所写的内容的话: int *const p必须在定义的时候就给p赋值,意思是要写成int *const p=&a才可以编译通过,仅仅是写成int *const p而未给p初始化那是编译不通过的。

为什么呢?

其实很好理解,const修饰的常量都必须在声明时立马定义,而后就再也不能修改了,指针p作为一个常量,也是要遵守这个规则的。