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 ** ?