C++PrimerPlus(第6版)中文版:Chapter7.3.5指针和const

本文详细探讨了C++中const关键字应用于指针的两种方式:指针指向常量对象和指针本身为常量。强调了const在不同情况下的约束效果,包括不能通过const指针修改变量值、禁止将const变量地址赋给非const指针等。同时,解释了为何应尽量使用const以避免无意修改并使函数兼容const和非const参数。最后,举例说明了const指针和常量指针的区别,以及它们在内存地址修改上的限制。
摘要由CSDN通过智能技术生成

将const 用于指针,有一些很微妙的地方,我们来一起讨论一下,本章节没有源程序,只有代码片段,看懂了有助于提高你面试成功率。

可以有两种不同的方式将const关键字用于指针。

  1. 第一种方法是让指针指向一个常量对象,这样强调的是这个对象是个常量,是常量就不能修改了,所以你不能用  *pointer 这种方式来修改变量的值。
  2. 第二种方法是将指针本身声明为常量,这样就强调了这个指针是个常量,常量是不可以修改的,这样整个指针所指的位置就是不可以修改的。

 第一种方法是让指针指向一个常量对象,这样强调的是这个对象是个常量,是常量就不能修改了,所以你不能用  *pointer 这种方式来修改变量的值。

int age=39;
const int* pt=&age;

上面的代码的意思是说指针*pt 就是一个常量,你不能对*pt做出修改,所以 *pt=89,这种代码就错了。在VS中会做出这样的提示:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误	C2373	“pt”: 重定义;不同的类型修饰符	pointer_all	D:\eCode\pointer_all.cpp	133	

然后微妙之处就在于:*pt是常量,并不意味着它指向的值是常量,age并不是常量,age还是可以改变的,只是不能通过*pt来改变,你直接修改age,还是可以的,就是不能用*pt来修改,因为,前面有const声明,告诉你这个*pt是const 是常量。

作者在这里提出了两个问题:

  1. 将const 变量的地址赋给指向const的指针,可以还是不可以?
  2. 将const变量的地址赋给常规指针,可以还是不可以?

现在来看看具体的答案:

  •  将const 变量的地址赋给指向const的指针:这样做是可以的,
const float g_earth=9.8//重力常数呗
const float* pe=&g_earth;//这么写是可以的,valid 有效的。这是个const 指针,指向一个const float 的变量

这个时候既不能使用 g_earth来修改值9.80,也不能用*pe来修改。

  • 将const变量的地址赋给常规指针:这样做是不行地, 

 

const float g_moon=9.8//重力常数呗
      float* p_wrong=&g_moon;//常规指针,指向了一个const float ,这么写是不可以的

如果你这么写,编译器VS中会出现两个错误:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误(活动)	E0144	"const float *" 类型的值不能用于初始化 "float *" 类型的实体	pointer_all	D:\eCode\pointer_all.cpp	137	
严重性	代码	说明	项目	文件	行	禁止显示状态
错误	C2440	“初始化”: 无法从“const float *”转换为“float *”	pointer_all	D:\eCode\pointer_all.cpp	137	

因此记住:C++禁止将const变量的地址赋给非const 指针(非const指针就是常规指针)

因此记住:如果数据类型本身并不是指针,则可以将const数据,或者非const数据的地址赋给指向const的指针 ,但是只能将非const数据的地址赋给非const指针(翻译过来就是:非const数据赋给常规指针,也就是说常规指针是不能取非const数据的地址的)。

假设有一个由const数据组成的数组:

const int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};

而禁止将常量数组的地址赋给非常量指针,意味着:不能将数组名作为参数产地给使用非常量形参的函数:

int main()
{int sum(int arr[],int n)//should have been const int arr[]
....
int j==sum(months,12)//不允许这样做
}




int sum_arr(int arr[], int n)
{
    int total = 0;
    cout << arr << "=arr, ";
    cout << sizeof(arr) << " =size of arr\n";
    for (int i = 0; i < n; i++)
        total = total + arr[i];
    return total;
}

如果你这样做了,VS中会出现如下错误:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误(活动)	E0167	"const int *" 类型的实参与 "int *" 类型的形参不兼容	pointer_all	D:\eCode\pointer_all.cpp	141	

严重性	代码	说明	项目	文件	行	禁止显示状态
错误	C2664	“int sum_arr(int [],int)”: 无法将参数 1 从“const int [12]”转换为“int []”	pointer_all	D:\eCode\pointer_all.cpp	141	

看见没有,你传入的是:const int*,就是说你传入的是const int* 指针,而原型声明中需要的是一个int* ,即需要的是int 指针,编译器认为这是两个不同的参数类型,然后编译就失败了。

也就是说:你函数声明的时候参数1如果不用const,那么就不能传数组名进去.

尽量使用const

将指针参数声明为指向常量数据的指针有两个理由:

这样可以避免由于无意间修改数据而导致编译错误;

使用const 可以使得函数能够处理const和非const实参,否则就只能处理非const数据。

如果条件允许,尽量将指针形参声明为指向const的指针

如果愿意,还可以看看下面的微妙之处:

int age=39;
const int* pt=&age;

前面已经说过,这么些*pt是常量是不可以将*pt赋给 别的值的,但是将一个新的地址赋给pt

int age=39;
const int* pt=&age;

int other_age=80;
pt=&other_age;//这样是可以的啊,但是仍然不能用*pt来修改它指向的值,原来是39,现在是80了

第二种使用const的方式使得无法修改指针的值:

int sloth=3;
const int *ps=&sloth;// 这是第一种:a pointer to const int 

//第二种在这里
int * const finger=&sloth;//这是第二种:a const pointer to int 

在这个第二种情况下,使得finger只能指向sloth,不能指向别的地方,如果你指了别的地方编译器报错如下:

严重性	代码	说明	项目	文件	行	禁止显示状态
错误(活动)	E0137	表达式必须是可修改的左值	pointer_all	D:\eCode\pointer_all.cpp	150	

看见了没有,在编译器那里,这个finger是个常量,是不能修改的左值。

我C++的语言的学习暂时高于段落,我需要去好好学习一下QT,现在都强调自主研发,还需要跨平台,接下来的博文都是QT,感谢支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值