(一)指针和const

const关键字加在定义变量之前。说明定义的变量是一个常变量

1
2
3
4
5
6
7
8
9
10
11
int a = 10;

int* p = &a;
//p是一个int类型的指针变量,保存a的地址
*p = 20; //可以通过解引用的方式修改保存地址中的值

const int* p1 = &a;
int const *p2 = &a;

int* const p3 = &a;
const int* const p4 = &a;

分析:

  • (常指针)p1、p2 指向a的地址,const修饰的是p1 和 p2,所以p1和p2的值可以修改,p1 和 p2的值不可修改
  • p3 指向a的地址,const修饰的是p3,所以p3的值不可修改,*p3的值可以修改
  • p4指向a的地址,从右向左,第一个const修饰p4的值,第二个const修饰p4的值,所以p4和p4的值都不可修改

结论:

看准 const 和 * 的位置:

  • const 在左边,const修饰 变量名;
  • const 在*右边,const修饰 变量名;

(二)能力缩小定律

(1)小试身手

我们对(一)进行小小地修改,看下面那句代码编译错误?

1
2
3
4
5
6
7
8
int a = 10;
int* p = &a;

const int* p1 = p;
int const *p2 = p;

int* const p3 = p;
const int* const p4 = p;

分析:

(1)从p指针的能力入手:p可改变,p也可改变
(2)const修饰 \
p1 ,缩小p1的 *p1能力,可以编译通过;
(3)p2和p1一样,可以编译通过
(4)const 修饰p3的值,不影响p自身的能力,编译通过
(5)右const修饰p4,左const修饰*p4,p4 和 *p4都不可改变,可以编译通过

结论:编译通过


(2)小试身手

这次我们在p的前面加上const,那这次的编译结果呢?

1
2
3
4
5
6
7
8
9
10
int a = 10;
const int* p = &a;

int* p0 = p;

const int* p1 = p;
int const *p2 = p;

int* const p3 = p;
const int* const p4 = p;

*分析:

  • 同样从p的能力入手,const修饰p,所以后面的语句有修改p的嫌疑都编译不通过
  • p0拥有*p0能力,具有修改*p的嫌疑,编译不通过
  • const修饰*p1和*p2,符合p的能力,可以编译通过
  • const修饰p3的指向,没有限制*p3的能力,有修改*p的嫌疑,编译不通过
  • 左const修饰*p4,右const修饰p4,限制了*p4能力,可以编译通过

结论:p0 p3编译不通过,其余可以编译通过


(3)小试身手

再次修改,那麽这次的编译结果呢?

1
2
3
4
5
6
7
8
9
10
int a = 10;
int* const p = &a;

int* p0 = p;

const int* p1 = p;
int const *p2 = p;

int* const p3 = p;
const int* const p4 = p;

分析:

  • 从p的能力入手,const修饰的是p的值,所有具有*p的能力
  • 由于后面都是一级指针,无法通过同级指针来修改p的指向(p的值),所以全部都可以编译通过

结论:都可以编译通过


(三)指针+引用

也可以看看这种形式的使用,下面的编译情况呢??

1
2
3
4
5
6
7
8
int a = 10;
int *p = &a;

int* p0 = p;

int *&s = p; //true
int &*q = p; //error

分析:主要难度就在后两句上,符号从右向左解释
int *&s = p;这句意思就是s是指针p的引用,所以可以编译通过
在这里插入图片描述
int&* q = p;这句话没有任何意思,编译错误
在这里插入图片描述


(四)指针+引用+const

在看懂上面的所有情况之后,再来看这种形式的使用,想必一定是手到擒来了吧,吧。

1
2
3
4
5
6
7
8
9
int a = 10;
int b = 20;
int* p = &a;

int*& s = p; //s是p指针的别名,可以通过修改s和*s,修改p的值和*p的值

const int*& s1 = p; //s1是p指针的别名,可以通过修改s1修改p的值; (vs2019不支持,vc6.0支持)
int* const &s2 = p; //s2是p指针的别名,可以通过*s2修改*p的值;
const int* const& s3 = p; //无法通过修改s3和*s3的值,修改p和*p的值

(1)const修饰p

1
2
3
4
5
6
7
8
9
int a = 10;
int b = 20;
int* const p = &a; //凡是后面增加了修改p的值的能力的语句都无法编译通过

int*& s = p; //可通过s改变p的值,编译错误

const int*& s1 = p; //可通过s1改变p的值,编译错误 (vs2019不支持,vc6.0支持)
int* const &s2 = p; // 类型匹配,编译通过
const int* const& s3 = p; //缩小能力,编译通过

(2)const修饰*p

1
2
3
4
5
6
7
8
9
int a = 10;
int b = 20;
int* const p = &a; //凡是后面增加了修改*p的值的能力的语句都无法编译通过

int*& s = p; //可通过*s改变*p的值,编译错误

const int*& s1 = p; //类型匹配,编译通过 (vs2019不支持,vc6.0支持)
int* const &s2 = p; // 可通过*s2改变*p的值,编译错误
const int* const& s3 = p;//缩小能力,编译通过