前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >EasyC++16,指针初探(二)

EasyC++16,指针初探(二)

作者头像
TechFlow-承志
发布2022-08-26 16:43:00
1560
发布2022-08-26 16:43:00
举报
文章被收录于专栏:TechFlow

作者 | 梁唐

大家好,我是梁唐。

这是EasyC++系列的第16篇,咱们继续聊聊C++中的指针。

指针初探(二)

危险的case

指针由于能够操作内存,所以如果使用的时候不够仔细,很容易引发一些意想不到的错误。

C++ Primer当中给了这样一个例子:

代码语言:javascript
复制
int *ptr;
*ptr = 2333;

在这段代码当中我们声明了一个int型的指针,并且将它指向了2333。然而,这里有一个问题,我们在声明指针的时候并没有进行初始化。没有初始化的指针并不为空,而是指向一个未知的地方。如果说它指向的是一个常量1200的地址,我们让它等于2333,那么之后当我们使用1200这个常量的时候,得到的结果都是2333。

更可怕的是,整个过程非常地隐蔽,很难察觉。debug的时候会令人抓狂。

所以千万不要修改一个没有初始化的指针指向的值。

指针和数字

C++ Primer当中还给了另外一个例子,当我们输出指针的时候,得到的是一串十六进制的数。那我们能不能反过来将一个十六进制的数赋值给指针呢?

代码语言:javascript
复制
int *p;
p = 0xB8000000;

答案是不行,因为类型不一致。虽然我们打印指针的时候看起来得到是十六进制数,但它的类型其实是指针类型,而不是整数类型。所以我们将一个整数赋值给一个指针是不行的,如果非要赋值,必须要进行类型转换。

代码语言:javascript
复制
int *p;
p = (int*) 0xB8000000;

但是这一转换之后显然又出现了一个问题,我们知道0xB8000000这个地址指向哪里么?显然不知道,自然也就说不清改了这里的值之后会引发什么结果。

所以虽然这么做可行,但也强烈不建议这样干。

new操作

前文说过使用指针有一个非常大的好处就是可以在程序运行的时候,动态分配内存。其实在C语言当中也有类似的功能,可以使用malloc来分配内存。不过在C++当中有了更好用的运算符——new

比如我们要动态创建一个int类型的变量,可以这样写:

代码语言:javascript
复制
int *ptr = new int;

new运算符根据之后的类型确定需要的内存大小,找到这样的内存之后,返回地址。刚好指针接收的值就是内存地址,因此刚好可以完成这样的赋值操作。

上面的代码也可以写成这样:

代码语言:javascript
复制
int a;
int *ptr = &a;

这两者有什么区别呢?表面上看没有区别,都是创建了一个int类型的变量。只不过第二种写法除了可以使用指针ptr之外,还可以使用变量名a来访问这个int

但实际上这两者的内部实现完全不同,我们直接通过变量名创建的变量它的值会被存储在栈内存当中,而通过new创建的对象则被存储在堆内存当中。栈内存是由系统自动分配,而堆内存则是由程序员进行申请使用。这两者的内存模型是完全不同的,我们会在之后的文章详细地讨论这点。目前简单来理解的话,就是堆内存更加灵活,它的空间也更大,可以存储下更大的数据。

delete操作

有了动态创建,自然也就有动态删除,所以C++当中有一个delete操作和new相对应。

delete运算符可以在变量使用结束之后,将内存归还给内存池。因为很多时候程序当中的变量都是一次性使用或者是有生命周期的,当生命周期结束,使命完成就没有必要继续占用着资源了。毕竟系统内的内存资源是有限的,尤其是在一些大型项目或者嵌入式系统当中,内存资源非常紧张。

delete运算符之后跟一个指针,它会释放改指针指向的内存。

代码语言:javascript
复制
int *ptr = new int;
delete ptr;

这里面有很多坑,千万要当心。首先是使用了new创建了内存之后,一定要记得delete,否则这块内存将会永远被占用无法得到释放,这种情况被称为内存泄漏(memory leak)。另外,我们不能delete一个已经delete过的指针,这也会引发严重错误。C++ Primer对此的描述是:什么情况都可能发生。当然也不能再使用一个已经被delete的指针,这会引发空指针错误。

指针对于C++来说是一把双刃剑,像是Java、Python、Go等其他语言,内存回收的工作都是由系统自动执行的。例如Java的JVM虚拟机设计了严密的GC(垃圾回收)机制,程序员无须关心内存的回收问题,全部交给程序自动完成。

而在C++当中,这一过程是由程序员手动执行的,某种程度上来说,这当然非常好,程序员拥有了很高的权限以及灵活度。但同样也是一个坑,尤其是在复杂系统当中,很难准确判断delete执行的时间。这会引发严重的问题,例如内存泄漏严重,野指针到处飞等……

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 危险的case
  • 指针和数字
  • new操作
  • delete操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档