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-03-27


评论