内存管理:理解引用计数

1.引用计数工作原理

●Retain    递增保留计数

●Release  递减保留计数

●Autorelease   待稍后清理“自动释放池”时,再递减保留计数。

*OC使用引用计数来管理内存,也就是说,每个对象都有个可以递增或者递减的计数器。如果想使某个对象继续存活,那就递增其引用计数,用完了之后就递减其计数。计数变为0,就表示没人关注此对象了,于是,就可以把它销毁。

*在iOS程序中,如果按引用树回溯,那么最终会发现一个根对象,为UIApplication对象。

2.属性存取方法中的内存管理

访问属性时,会用到相关实例变量的获取方法及设置方法,若属性为“strong关系”,则设置的属性值会保留。例如:

- (void)setFoo:(id)foo {

    [foo retain];

    [_foo release];

    _foo = foo;

}

此方法将保留新值并释放旧值,然后更新实例变量,令其指向新值。顺序很重要,假如还未保留新值就把旧值给释放了,而且两个值又指向同一对象,那么先执行的release操作就可能导致系统将此对象永久回收。而后续的retain操作则无法令这个已经彻底回收的对象复生,于是实例变量就成了悬挂指针。

3.自动释放池

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

例如:

- (NSString *)stringValue {

    NSString *str = [[NSString alloc] initWithFormat:@"str"];

    return str;

}

因为调用alloc此时对象保留计数会增加1,如果在方法内部调用release会导致还没等方法返回,系统就将该对象进行回收。这里应该调用autorelease,它会在稍后释放对象,从而给调用者留下了足够长的时间,使其可以在需要时先保留返回值。实际上,释放操作会在清空最外层的自动释放池时执行,就是当前线程的下一次事件循环。

- (NSString *)stringValue {

    NSString *str = [[NSString alloc] initWithFormat:@"str"];

    return [str autorelease];

}

修改之后,stringValue方法把NSString对象返回给调用者,此对象必然存活。

但是,假如要持有此对象的话,比如将其设置给实例变量,那就需要保留,并与稍后释放:

_instanceVariable = [[self stringValue] retain];

//...do...

[_instanceVariable release];

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

4.保留环

互相强引用导致循环引用,通常采用“弱引用”来解决此问题,或时从外界命令循环中的某个对象不在保留另外一个对象。

 

转载于:https://www.cnblogs.com/byxixiblogs/p/8479274.html

你可能感兴趣的:(内存管理:理解引用计数)