对于iOS中dealloc时retainCount仍为1的一种解释

第一次写博客,必然有一些不是很好的地方,欢迎大家指正。本文仅代表个人观点,如果与朋友你的观点有些许出入,欢迎提出来共同讨论。

当前问题:
今天有朋友提出了一个问题,他写了一个Dog类,然后在Dog类里重写了dealloc方法,并在dealloc里打印了dog的retainCount,结果发现retainCount = 1。这与我们平时的认识:retainCount为0时释放对象仿佛是相违背的。代码比较简单,就不贴了,直接上两个反映问题的图片。
main

dog


原来的认知:
原来的时候我们对内存管理的认知一直都是这样的的:retain(等)能够使retainCount+1,release能够使retainCount-1,当对象的retainCount=0的时候,系统将会调用对象的dealloc方法并把对象销毁。这有几个关键点,当retainCount=0,才会调用dealloc,retainCount=0可以说是系统判断的标志。但是这种认知明显与我们先前提出的问题不相符。

度娘怎么说
针对这个问题,我个人也确实是第一次见,之前学习时也没有留意过,于是度娘了一番。得到的结论大多数是说,retainCount是不准确的,不用太在意这个,只要确保我们的retain、release等等这些对引用计数的操作没问题就OK。然后也试着去找了一下苹果官方文档,找到了一张图
苹果
这张图中很明显的写到,当对象(图中蓝色圈圈)在最后一次release时,retainCount减为0,然后对象被销毁。

这和我们上面提到的,在dealloc打印retainCount结果为1仿佛也是相违背的。于是,根据种种情况,提出了自己的看法。

本人观点
观点先说:这是苹果的优化,原因是为了节省对象的引用计数-1的开销。针对我的观点,先给出两个简单地流程图,然后再来解释。
方案1

方案2

方案1对应的是我们的常规认知地处理流程
方案2对应的是我提出的观点的处理流程

两个流程图中虽然步骤数看起来差不多,但是当进入流程前dog的retainCount=1时,明显方案2会少一步(即retainCount-1)。
那么为什么要这么做呢?
当dog的retainCount只有1的时候,如果我们对它进行release操作,也即我们不再持有dog了,系统可以去销毁它了,我们已经不需要不在意它了。那么此时,系统可能会这么想,既然这个dog马上要被它的主人抛弃了(别无它意),那么我(系统)又何必在它身上浪费时间来处理retainCount呢?反正即使retainCount-1它也会马上销毁,我进行-1也并没有什么太大卵用,还要浪费资源来处理,那我还不如就直接销毁它就OK了。
于是就出现了我们开头提到的现象,当retainCount>1时,进行retain、release没有任何问题,但是当retainCount=1时,如果我们release一下,系统会预料到dog的retainCount将要=0,于是就直接启动销毁流程,而并不会真的把dog的retainCount减到0再去启销毁放流程。

总结
其实我们平时的认知并没有太大的问题,dealloc确实是在对象需要销毁的时候被调用的,而对象需要销毁的时候也就是没有谁再需要它的时候,也即retainCount = 0 的时候。我们这么理解没有错,但是系统是机智的,它偷天换日把“retainCount = 0 ”理解成了 “retainCount = 1 && release 一下“。
所以,网友们说的其实也没错,不要太在意这些细节,把重点放在管理你的retain、release上。苹果为你优化的,就让他去优化吧,我们管好我们的代码。最后为retainCount平反一下,retainCount是应该准确的,只是它有时候会在不影响程序流程的情况下偷个懒。
PS:虽然看起来只是在一个对象的销毁中省了一个retainCount-1的操作,但是一个程序中可能会有成千上万的对象,这笔资源加起来应该也是不少的吧……
如果我的观点有误,欢迎大家指出。
如果大家有其它的观点,欢迎提出来一同讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值