159-C++基础(const与一二级指针的结合应用)

1、const的初步认识

const怎么理解?

  • const修饰的变量不能够再作为左值!!!
  • 初始化完成后,值不能被修改!!!

在这里插入图片描述

  • 图示b=30;语句错误。因为const修饰b的值为20,之后,b的值就不能被修改了!

2、C和C++中const的区别是什么?

C中的const

  • 我们在C文件中使用const,在C语言,把const修饰的量和普通的量都是变量,只是const修饰的变量不能作为左值。
    在这里插入图片描述
  • 在C语言中,const修饰的量可以不初始化,但是就没有机会再给它合法的值了,因为不能作为左值
  • 在C中,const修饰的量不叫常量,叫做常变量

下面这个数组写法是错误的,因为a不是常量,是常变量,所以它不能作为常量/常量表达式来使用。
在这里插入图片描述

在这里插入图片描述
面试问题:
在这里插入图片描述

  • 指针p指向的是a的内存;
  • const只是语法上保证修饰的量a不能作为左值,即不能作为左值修改;
  • 但是内存是可以修改的,我们通过指针就可以修改了;
  • 我们也可以通过插入汇编指令去修改a的内存;

我们看到,a的内存的值已经被改为30了。
因为在C语言中,a是常变量!!!
在这里插入图片描述

C++中的const

  • 在C++中,对于const修饰的量是必须要进行初始化的

在这里插入图片描述
可以看到,不初始化是无法通过编译的。
在这里插入图片描述
C++的const必须初始化,叫做常量。
在这里插入图片描述

  • 既然是常量,是可以来定义数组的(因为是常量,所以可以作为数组的下标哦!)

在这里插入图片描述
我们把a进行强转看看:

在这里插入图片描述

在这里插入图片描述
可以发现,打印出来的值和在C文件中打印出来的值不一样。

因为对const的编译方式不同:

  • C中,const就是当作一个变量来编译生成指令的
  • 但是在C++中,所有出现const常量名字的地方,都被常量的初始化值给替换了!!!

数组定义:
在这里插入图片描述
在C++中相当于将数组长度a直接替换了:(是用20在定义数组的长度。)
在这里插入图片描述
在这行代码中:

  • 出现const常量名字的地方,都直接用常量的值进行替换;

在这里插入图片描述
在这里插入图片描述

问题:p指针到底有没有修改a的内存值?
在这里插入图片描述

  • 改了,a的内存值已经被修改成30了。
  • *pa的内存的值改为30了,但是编译器在编译时是把常量a都用20替换了,和a的内存就没有关系了。
  • 所以,const修饰必须初始化,不然拿谁替换啊???

我们再来看:

C++文件:
在这里插入图片描述

用变量b初始化a,但是变量的值是多少只有在运行的时候才知道,所以我们可以认为,a的地方都用变量b来替换了
在这里插入图片描述
在这里插入图片描述

此时的a已经相当于退化变成C语言中的常变量了。不能定义数组了,也不能替换了。

  • 在C++中,const初始值是一个常量,则这个就是一个常量;是变量,就是常变量

3、const与一级指针的结合应用

后面给空指针都是用nullptr。

  • 因为在C++中,NULL是空指针或者0值。NULL不区分指针和整数。

const修饰的量 叫常量,和普通变量的区别是什么? C++有两点区别?

  • 1、编译方式不同 (编译过程中所有出现常量名字的地方,都会用常量的初值来替换)
  • 2、不能作为左值了

C++中const修饰的量常出现的错误是:

  • 常量不能再作为左值 (不能直接修改常量的值)
  • 不能把常量的地址泄露给一个普通的指针或者普通的引用变量 (不可以间接修改常量的值)
  • 这2点是C++编译器可以检测出来报错的。

我们看下面代码:
在这里插入图片描述
因为指针没有做任何的修饰,指针解引用可以随便赋值的,会间接修改。

无法编译通过:
在这里插入图片描述
那怎么转换呢?

const和一级指针的结合:有4种情况
在这里插入图片描述
C++的语言规范:const修饰的是离它最近的类型。

1、const int *p = &a;

const int *p = &a;
  • const修饰的就是int了,因为int本身就可以组成一个类型,不需要再带后面的* 。

  • 我们不关心const修饰的是什么类型,我们关心的是const修饰的是什么表达式。什么表达式不能再被赋值了。

  • 我们把修饰的类型去掉,就是const修饰的表达式了:*p

  • *p就不能被赋值了。

  • *p被const修饰了,const修饰了指针p的指向,指向的东西不能被赋值了。

  • 但是指针本身可以被赋值,因为p本身没有被const修饰。(p=&b是可以的)

  • p可以任意指向不同的int类型的内存,但是不能通过指针间接修改指向的内存的值。

2、int const* p;(和第1个一样的)

int const* p;
  • const修饰的是离它最近的类型,但是*不是类型哦,不能用 * 定义变量,所以修饰的还是int。
  • const修饰的表达式还是 *p;

3、int *const p = &a;

int *const p = &a; 

  • 这个const修饰的类型是int *了,因为 * 自己不能单独作为类型,所以再往前走,就是int *了
  • 去掉const修饰的类型,就是const修饰的表达式,就是p本身了;
  • p本身是常量,不能被修改(p = & c,是错的),但是 *p没有被const修饰,可以修改(*p = 20是可以的)。
  • 这个指针p现在是常量,不能再指向其它内存,但是可以通过指针解引用修改指向的内存的值

4、const int *const p = &a;

  • 上面的情况的综合
  • 前面的const修饰的类型是int,所以const修饰的表达式是*p,*所以 p不能被赋值。
  • 后面的 const修饰的类型是int *,所以修饰的表达式是p,所以p不能被赋值。

举例:
在这里插入图片描述这样*p就不能被解引用了。

下面几种写法都可以指向a:
在这里插入图片描述

在这里插入图片描述

  • 总结:
    在这里插入图片描述

我们看这个是什么情况?
在这里插入图片描述
直接先说结果:其实是int* <= int*,const没有参与作用!
在这里插入图片描述

我们先来看下面:
在这里插入图片描述
在这里插入图片描述

  • const如果右边没有指针*的话,const是不参与类型的!!!
  • const只用来表示q2是常量,q2不能作为左值

其实是int <= int,const没有参与作用!**
在这里插入图片描述

下面这两个也是都没有问题的:
在这里插入图片描述

总结const和指针的类型转换公式:
左值         =   右值 
int*        =    const int*    是错误的!
const int*  =    int*          是可以的!

面试案例

在这里插入图片描述
int *q=p是错误的。const int * 不能赋值给int *

在这里插入图片描述

在这里插入图片描述

4、const与二级指针的结合应用

在这里插入图片描述
左边的类型是const int**,右边的类型是int **

这个类型转换是正确还是错误的???
我们看下面示意图:
在这里插入图片描述
对于这个二级指针q,它的表达式组成就这3种:

  • q(表示本身的值)
  • *q(表示它所指向的一级指针p的值)
  • **q(表示它所指向的一级指针p指向的变量a的值)

const和二级指针的结合:(有3种情况)
在这里插入图片描述

  • 第一种,const修饰的是int类型,所以**q不能被赋值,但是* q可以被修改赋值,q本身也可以被赋值。
  • 第二种,const修饰的是int * 类型,所以 * q不能被赋值,但是q和 **q`可以被赋值。
  • 第三种,const修饰的是int * * 类型,所以q不能被赋值,但是*q **q可以被赋值。
总结const和指针的类型转换公式:
左值    =   右值 
int*    =    const int*    是错误的!
const int*  =   int*       是可以的!

const和多级指针结合的时候,两边都必须要有const,一边有一边没有是不行的
int**  =  const int**        是错误的!
const int**  =  int**        是错误的!

int**  =  int*const*(这个const是和一级指针的结合,后面是1*) 是错误的!
==* =const * 所以是错误的!!!

int*const*  =  int**     是可以的!(*转成const*是可以的)
const* = * 是可以的

在这里插入图片描述

我们看:

  • p是普通的指针,*q指向p这个普通的指针, * q 和p访问的是同一块内存,如果我对 * q赋值,相当于是把内容写到这块内存中,*q存的是const int *,也就是把整型常量的地址是赋值给 *q,const int b=20,可以把&b赋值给 *q,但是p是普通的指针啊,p可以解引用修改整个整型常量的地址啊,所以肯定不行啊!!!不能把常量的地址泄露给一个普通的指针!!!

相当于把这个整型地址放到普通的一级指针变量里面。
但是常量的地址赋值给普通的指针p(因为p和*q等价)了,这是不行的。

怎么改呢???

解决方法1:

  • 此时 * p不能被赋值了。就可以了。
    在这里插入图片描述
    解决方法2:在这里插入图片描述
    让*q不能赋值。

5、总结,笔试题

例1

在这里插入图片描述
A错:
在这里插入图片描述
B正确:
在这里插入图片描述
C正确。 const不参与类型。都是int*
在这里插入图片描述

例2

在这里插入图片描述
在这里插入图片描述

A错误。 把常量的地址给普通的指针了。
在这里插入图片描述
B正确。
在这里插入图片描述
C正确。
在这里插入图片描述
D错误。
在这里插入图片描述
调整下,变为:
在这里插入图片描述
E错误。
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liufeng2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值