为什么要用C++智能指针

对于C/C++程序员来说,指针是天堂,同时指针也是地狱。指针有多少好处,又有多少让人头疼的问题我们这里就不多说了。但为了局部解决指针的问题,我们提出了智能指针这个概念。

 

实际上,我一直不明白,智能指针用于干什么!直到我遇到有关栈和堆问题的时候,才依稀有了点感悟,我现在的感悟几乎肯定是不全面的,但是很重要。

几乎有关指针的问题的出现集中在指针指向堆上空间的时候,为什么呢?

如果指针指向的是栈上的空间,我们知道这里的空间是有系统自动管理的,申明释放都是由系统根据栈的策略来进行的。我们能够干预的部分很少。

而对于指向堆空间的指针,由于申请(new),和释放(free)必须要程序员显示的进行调用,并且该空间的生命周期在new语句和free之间。

注意,这就是当年设计C/C++的伟大之处:事实上所有名字的空间(变量)都只会存在于栈(或者更低的内存空间中),而栈根据它特有的先进后出的策略,实现了C/C++语言中复杂的变量生命周期与作用域问题。但是这还不够,对于一个C/C++程序而言,栈就像是一个工作间,有关程序的推进总调度都在这里,它的空间不是很大(有操作系统规定:1M2M),在逐个读取指令执行指令的过程中,需要读取其它空间的空间数据,如“代码区”,“常量区”,“全局/静态区”等等,还有一个非常重要的区域,也是程序得以弹性作业的区域——“堆”,堆区的空间没有大小限制,几乎以操作系统能够承载的最大虚拟存储空间为上限。这里想是一个任意的、临时仓库区。要申请什么空间,在这里申请就是,然后返回一个“句柄”(指针),给程序的“总调令区”——栈区,然后程序可以通过那个指针(栈区)来控制那个堆区的空间。于是似乎整个内存分布过程变得很完美。

但是,麻烦就发生在堆区的空间有用户自定申请,和组织释放,并且它还没有自己的名称(通常的变量名),而只是被指针(地址)指着,而指针有一个可以改变内容的变量(不想变量名和引用名那样的声明之后就不会改变指向的哪个地方)。

这样的境况导致的后果就是,程序员必须很仔细的申请并给出对应的释放语句,但是由于程序的复杂都增大,判断、循环、递归这样的语句会让程序的走向处于不定境地。很有可能出现内存泄露的问题。

1)内存泄露及其检测的详细内容这里就不介绍了。不过内存泄露的关键含义就是,操作系统将空间分配给你了,但是那个空间被你申请并使用之后就在也没有用,并且没有响应的释放语句,一句话,该空间不再补任何指针或引用所引用,成了一个幽灵空间。操作系统以为你在控制它,但其实你并没有控制它。

那么为了解决内存泄露问题,一个解决方法是,仔细的、在多个可能的“路口”放上free的语句,但是这又可能导致另外一个问题,就是重复释放问题。

2)重复释放问题发生在程序通过freedelete语句释放已经不属于该程序的空间。而是非常危险的,比起内存泄露,重复释放是一个非常严重的问题。有可能你第二次free的空间已经被别的程序所使用,所以C/C++中视这种错误为致命错误。(也就是说,我容许你局部的浪费,但绝对不容许你释放(使用)别人的东西)

事实上,还有一个问题是指向堆对象指针需要注意的,就是在释放之后,该指针仍然指向那个已经不属于该程序的空间,并且,由于指针的“霸气外漏”,它几乎能够仍然对该空间进行读甚至是写操作,但实验证明,系统不认为该空间不属于该程序。这是什么状况,就是你的指针偷偷的使用了别人的地盘,而你自己不知道,系统也不知道。这种行为几乎是没有什么用处的(如果你要用,就大大方法的向系统申请呗),而且有可能带来恐怖的坏处(改写别人家的空间内容)。所以这种行为的出现只能定位为——程序员没有严加看守,导致程序异常执行。所以前面我们讲过解决这一个问题的方法就是在执行delete删除之后,请一定记得,要将那个指针指向0也就是null,或者是一个你控制的空间,或者直接delete掉(如果它本身也是堆上对象)。

 

从上面可以看出,使用堆上对象的时候,需要我们保证“对象一定会被释放,但只能释放一次,并且释放后指向该对象的指针应该马上归0

要达到上面的要求,除了硬性要求程序员在设计的时候要小心,(而这几乎是无法避免的),还该有其它的一些方法(我们几乎可以把这些方法称为指针设计模式了)。硬性要求程序员时刻注意那些并非他“主营业务”的东西会转移程序员的核心注意力。

于是,我们思考出一个办法,这个办法就是使用智能指针。还是前面说的那句话,智能指针可能还有其他的用处,但这里我只涉及上面介绍的问题。

智能指针

实际上,智能指针是借鉴了java内存回收机制(引用计数器机制)。(或许是java在设计的时候借鉴了这个解决C++内存回收问题的机制,无所谓啦)。

智能指针的实现方法可以再很多地方找到,事实上到现在,我也不确定如何实现,但是要自己思考而不是被动的学习。自己思考能够得出为什么要这么实现,被动的学习基本只知道“哦!是这样的哦!”


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值