首先明确这几个术语的具体含义:
const pointer
,即指针自己是常量pointer to a constant
,即不能通过该指针去修改目标的指针a constant pointer to a constant
,指针自己既是常量,也不能通过该指针去修改目标的指针从英语可以很快速的理解这几个术语的含义,但是由于翻译的问题,就导致大家在初学 C++ 时会很晕头转向,被这几个概念搞的摸不清头脑
同样由于翻译的问题,还存在下面这组术语:
而第二组的翻译和第一组的翻译在常量指针的位置刚好出现了两种截然不同的结果,或许这就是很多人在网上搜文章时感觉都不是很统一的原因吧,一部分文章按照第一组翻译去解释意思,另一部分文章按照第二组去解释就会导致看下来更加的晕头转向了
防止读者产生误会,我会在后续使用英语名来代替中文名,另外读者不用过分纠结中文名字,只需要能够分辨清楚 const pointer
和 pointer to a constant
的定义方法与用法即可
const pointer
意为指针自己是常量,所以无法更改指针的指向,并且一定要对指针进行初始化
定义方法如下:
int a=1;
int *const p1=&a;
const
放在 *
后面,强调修饰的是 p1
,所以 p1
是常量,这样有助于读者更好的理解
pointer to a constant
意为指向常量的指针,指针本身是可以变化的,而且指针可以指向变量也可以指向常量,唯一不行的是通过指针去修改变/常量的值
定义方法如下:
const int *p1;
或者
int const *p1;
const
放在 *
前面,强调修饰的是 *p1
,所以 *p1
是常量,这样有助于读者更好的理解
pointer to a constant
不要求进行初始化,因为指针本身还是一个变量,只有常量才会要求必须进行初始化
下面的表格给出了 pointer to a constantt
和被指对象的类型的兼容性,表格中所有指针均可以重新指向别的对象
pointer to a constant(指向常量的指针) | poiner(普通指针) | |
---|---|---|
constant(常量) | √ | × |
variable(变量) | √ | √ |
下面来逐一分析表格中的情况:
对应下列的代码:
const int a=1;
const int *p1=&a;
该代码定义了一个常量 a
,并且将指针 p1
指向了常量 a
,常量 a
不可以被任何方式进行修改
假设下列的语句是合法的(下列语句是错误的):
const int a=1;
int *p1=&a;
那么就可以通过 *p1
来修改常量 a
的值,这与常量的概念不符,故不可以让普通指针指向常量
对应下列的代码:
int a=1;
const int *p1=&a;
该代码定义了一个常量 a
,并且将指针 p1
指向了变量 a
,变量 a
可以被直接修改,但是不可以通过 *p1
的方式对 a
进行修改
对应下列的代码:
int a=1;
int *p1=&a;
该代码定义了一个常量 a
,并且将指针 p1
指向了变量 a
,变量 a
可以被直接或者使用 *p1
修改
这里先明确一个概念:在上述的代码中,只是涉及到了一层间接关系,即指针指向的是基本数据类型(不是指针),而在多层间接关系中,上述的部分规则将会不再适用
例如下面的代码在一层间接关系中是正确的:
int a=1;
const int *p1=&a;
pointer to a constant
可以与变量进行兼容,只是不能通过指针修改变量
而在二层间接关系时,这样的代码就会失效:
int a=1;
int *p2 = &a;
const int **p3 = &p2;
pointer to a constant
不能和普通指针兼容,若要使 p3
获得 p2
的地址,可以做如下的改动:
int a=1;
int *p2 = &a;
int **p3 = &p2;
或者
int a=1;
const int *p2 = &a;
const int **p3 = &p2;
在涉及到多层间接关系时,不允许 const
和 non-const
进行混用
在进行函数调用时,若传参是数组,由于传递的时数组首地址,则可能调用函数时修改了原数组的内容,所以可以在定义函数时,声明 pointer to a constant
的形参,来防止函数内部修改数组,例如:
#include
using namespace std;
int add(const int *begin,const int *end){
int sum=0;
for(;begin!=end;begin++)
sum+=(*begin);
return sum;
}
int main(){
int arr[5]{1,2,30};
cout<<add(arr,arr+5);
return 0;
}
定义 add
函数时,形参声明为 pointer to const
防止对数组元素进行修改,同时还带来一个好处:不管入参是否为常量数组,它都可以进行接收,例如在主函数中,把 arr
改为 const
修饰,程序也可以运行,而如果是普通指针用作形参,则不能接收常量数组
a constant pointer to a constant
含义为:指针的指向不可以改变,指针可以指向变量也可以指向常量,但是不能通过指针去修改变/常量的值,它的性质就像是 const pointer
和 pointer to const
的结合体
定义方法如下:
int a=1;
const int *const p1=&a;
或者
int a=1;
int const*const p1=&a;