指针和const (const int *,int const * 和 int * const)
c++ pp page 182
将指针和const结合有两种用法:
1.让指针指向一个常量对象,即该指针是一个指向 const 的指针(指向常量的指针),这样可以防止使用该指针来修改其指向的那个值,但是可以改变指针指向的位置(这样记:const 修饰其后面紧跟的词)
int age = 30; const int * pt = &age;
上述代码声明了一个指向const int 的指针(const int * 是一种类型,是指向const int 的指针)
注意,int const * 和 const int *毫无区别。
在上述代码中,不能使用指针pt来修改age的值,如
*pt = 20; //not allowed cin>>*pt; //not allowed
但由于变量age并不是一个常量变量,所以仍然可以使用age变量来修改自己的值
age = 10; //allowed
上述代码表明,可以将常规变量的地址赋给 指向const的指针(但仅当只有一层间接关系时,如指针指向基本数据时,才可以将非const地址或指针赋给const指针);
我们可以使用const在传递数组参数时保护原数据,即在声明形参时使用关键字const(c++ pp page179)
void show(const int * arr); //or void show(const int arr[]) int main() { int a[3] = {1,2,3}; show(a); } void show(a) { ... }
注意上述代码中show()函数进行原型声明时,使用了const关键字,可以防止函数无意中修改数组的内容。
------------------------------------------------------------------
注意,数组名是指针常量,上述代码将指针常量赋给普通指针,这样是可以的;
这与下面提到的 不能将const的地址赋给常规指针矛盾?
但是不能将常量指针(指向const的指针)赋给常规指针,如下图:
-------------------------------------------------------------------------------
如果是常量变量(const 变量),则只能将其地址赋给 指向const的指针,即,不能将const的地址赋给常规指针,如下所示:
const float a = 1.63; float * b = &a; //not allowed
所以,如果有一个由const数据组成的数组,我们就不能将该常量数组的地址赋给非常量指针,这就意味着不能将数组名作为参数传递给使用非常量形参的函数:
const int month[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; int sum(int arr[] , int n); //should have been const int arr[] ... int j = sum(month,12);//now allowed
2.将指针本身声明为常量,这样可以防止改变指针指向的位置
int b = 3; int * const a = &b;
上述代码中,指针a只能指向b,不能指向其他地方;但可以通过 *a 修改b的值。
注意:
int b = 3; const int * a = &a;//一个指向const int 的指针 int * const a = &a;//一个const指针指向int
----------------------------2022/3/11--------------------
void f(int a); ... const int x = 1; f(x);
上述程序是可以的,注意之前的表述:
如果数据类型本身并不是指针,则可以将const数据或非const数据的地址赋给指向const的指针,但只能将非const数据的地址赋给非const指针。
此外,对于引用做参数也是该情况:const引用做形参可以处理常量和非常量实参,普通引用做形参只能处理非const实参。p216
即const做形参优势可以体现在指针和引用两个方面。
因此上述程序是可以的,但下面程序是错误的:
void f(int* a) { return 1; } ... int b = 1; const int *x = &b; f(x);
该程序就将const数据的地址赋给了普通指针。