自动释放池

在oc的引用计数架构中,自动释放池是一项重要特性,调用release会立刻递减对象的保留计数(而且还可能令系统回收此对象),然而有时候可以不调用它,改为调用autorelease,此方法会在稍后递减计数,通常是在下一次“事件循环”时递减,不过也可能执行的更早一些。

此特性很有用,尤其说是在方法中返回对象时更应该用它,在这种情况下,我们并不是想令方法调用者手工保留其值,比方说,有下面这个方法:

- (NSString *)stringValue{

    NSString *str = [[NSString alloc]initWithFormat:@"I am this: %@",self];

   return str;

}

此时返回的str对象其保留计数比期望值要多1(+1 retain count),因为调用alloc会令保留计数加1,而又没有与之对应的释放操作。保留计数多1,就意味着调用者要负责处理多出来的这一次保留操作。必须设法将其抵消,这并不是说计数本身就一定是1,他可能大于1,不过那取决于“initWithFormat:”方法内的实现细节,你要考虑的是如何将多出来的这一次保留操作抵消。

但是不能再方法内释放str,否则还没等方法返回,系统就把该对象回收了,这里应该用autorelease,他会在稍后释放对象,从而给调用者留下了足够长的时间,使其可以在需要时先保留返回值,换句话说,此方法可以保证对象在跨越“方法调用边界”后一定存活,实际上,释放操作会在清空最外层的自动释放池时执行,除非你有自己的释放池,否则这个实际指的就是当前线程的下一次事件循环,改写stringValue方法,使用autorelease来释放对象:

-(NSString *)stringValue{

    NSString *str= [[NSString alloc]initWithFormat:@"I am this:%@",self];

   return [str autorelease];

}

修改之后,stringValue方法把NSString对象返回给调用者,此对象必然存活,所以我们能够像下面这样使用它:

NSString *str = [self stringValue];

NSLog(@"The string is:%@",str);

由于返回的str对象于稍后自动释放,所以多出来的那一次保留操作到时自然就会抵消,无需再执行内存管理操作,因为自动释放池中的释放操作要等到下一次时间循环时才会执行,所以NSLog语句在使用str对象前不需要手工执行保留操作,但是,假如要持有此对象的话(比如将其设置给实例变量)那就需要保留,并与稍后释放:

_instanceVariable = [[self stringValue]retain];

[_instanceVariable release];

由此可见,autorelease能延长对象生命期,使其在跨越方法调用边界后依然可以存活一段时间。

保留环

使用引用计数机制时,经常会注意的一个问题就是“保留环”,也就是呈环状相互引用的多个对象,这将导致内存泄漏,因为循环中的对象其保留计数不会降为0,对于循环中的每个对象来说,至少还有另外一个对象引用着他,下图里的每个对象都引用了另外两个对象之中的一个,在这个循环里,所有对象的保留计数都是1.


在垃圾收集环境中,通常将这种情况认定为“孤岛”。此时,垃圾收集器会把三个对象全部都回收走,而在oc的引用计数架构中,则享受不到这个便利,通常采用“弱引用”来解决,或是从外界命令循环中的某个对象不再保留另外一个对象,这两个办法都能打破保留环,从而避免内存泄漏。

要点:

1、引用计数机制通过可以递增递减的计数器来管理内存,对象创建好之后,其保留计数至少为1,若保留计数为正,则对象继续存活,当保留计数降为0时,对象就被销毁了。

2、在对象生命期中,其余对象通过引用来保留或释放对象,保留与释放操作分别会递增及递减保留计数。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值