将const 用于指针,有一些很微妙的地方,我们来一起讨论一下,本章节没有源程序,只有代码片段,看懂了有助于提高你面试成功率。
可以有两种不同的方式将const关键字用于指针。
- 第一种方法是让指针指向一个常量对象,这样强调的是这个对象是个常量,是常量就不能修改了,所以你不能用 *pointer 这种方式来修改变量的值。
- 第二种方法是将指针本身声明为常量,这样就强调了这个指针是个常量,常量是不可以修改的,这样整个指针所指的位置就是不可以修改的。
第一种方法是让指针指向一个常量对象,这样强调的是这个对象是个常量,是常量就不能修改了,所以你不能用 *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 是常量。
作者在这里提出了两个问题:
- 将const 变量的地址赋给指向const的指针,可以还是不可以?
- 将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,感谢支持。