const int ** = int ** ?

const int ** = int ** ?

一直以来我都觉得自己的 const 完全学会了,直到我的朋友问了我一个问题我才知道我是学废了 doge

本文包括判断 const 修饰内容的方法和标题行不通的原因

标题里的内容是无法通过编译的,按我原本的理解,这应该是能过编译的,说明我的理解有问题,让我来分析分析

1
2
3
4
5
6
int a = 5;
int * p_a = &a;

const int * c_p_a = p_a; // 正确

const int ** c_p_p_a = &p_a; // 错误

关于 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 无法改变其指向指针指向的内容,但它可以改变自身的内容和它指向的指针的内容

我就是这么想的,然而这是错的

一个指针可以保证它指向的指针指向内容不被改变?这管的确实太宽了,是不被允许的

仔细想想二级指针是如何被我们使用的就知道了:

  1. const int ** c_p_p_a,解一次引用*c_p_p_a,解两次引用**c_p_p_a

  2. 我们如果要改变 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 里是这样解释的

作者

Meow-2

发布于

2022-03-13

更新于

2022-11-06


评论