const int ** = int ** ?
一直以来我都觉得自己的const完全学会了,直到我的朋友问了我一个问题我才知道我是学废了doge
本文包括判断const修饰内容的方法和标题行不通的原因
标题里的内容是无法通过编译的,按我原本的理解,这应该是能过编译的,说明我的理解有问题,让我来分析分析
1 | int a = 5; |
关于const修饰的对象
首先,这两个const修饰的都是int而非指针,这一点很好判断
只需要从右往左读一遍就明白了:
const int * c_p_a : c_p_a is a point to const int,c_p_a是指向常量int的指针
const int ** c_p_p_a : c_p_p_a is a point to a point to const int,c_p_p_a是一个指针,指向一个指向常量的指针
举一反三:
int const * a : a is a point to const int,a是一个指向常量的指针
int * const a : a is a const point to int,a是一个常量指针指向int
const int * const * a : a is a point to const point to const int,a是一个指针指向一个常量指针,该常量指针指向const int
const int * a[] : a is a array which contains points to const int,a是一个数组,里面包含了指向常量的指针
关于const的作用
const int * 可以用int * 赋值,然后c_p_a无法改变其指向的int的内容,但它可以改变自身的内容
同理const int ** 应该可以用int ** 赋值,然后c_p_p_a无法改变其指向指针指向的内容,但它可以改变自身的内容和它指向的指针的内容
我就是这么想的,然而这是错的
一个指针可以保证它指向的指针指向内容不被改变?这管的确实太宽了,是不被允许的
仔细想想二级指针是如何被我们使用的就知道了:
const int ** c_p_p_a
,解一次引用*c_p_p_a
,解两次引用**c_p_p_a
我们如果要改变c_p_p_a指向的指向的内容为1,就需要
**c_p_p_a = 1
(按我之前的想法,这个语句是不被允许的)
但实际上这个语句跟c_p_p_a根本没关系,换个写法就清楚了,
*(*c_p_p_a)=1
,在解一次引用之后,实际上就是解引用得到的指针的事了,
它要不要改变他指向的值,c_p_p_a根本管不着
所以正确的写法是const int ** = &(const int *),这样c_p_p_a指向指向的值才不会被改变
当然int * const * int = int ** 是可以的,简而言之,一个指针只能决定它指向的内容能不能被改变,而不能决定它指向指向的内容能不能被改变
后记
const int * const * a = int ** 是可以的,因为*a一旦是确定的常量,那么编译器也就容易将其指向的内容标记为常量,就像const int * const = int *是正确的一样
对于const int ** = int **, cppreference里是这样解释的

const int ** = int ** ?