内存管理之引用计数

来源:互联网 发布:淘宝直通车标志图片 编辑:程序博客网 时间:2024/06/09 21:26

注意以下都是针对MRC下的

我们都知道OC采用引用计数规则来管理内存。
就是持有一个对象时,引用计数加1,不需要时就减1。等到引用计数为0时,证明不需要这个对象了,所以,系统会自动回收这块内存,即自动调用dealloc方法。

比如:
Person *p = [[Person alloc] init];
此时内存状态是这样的。
这里写图片描述

引用计数其实就是表示,此时有几个指针变量在用它。

那么当情况变成这样的时候呢。
(细节地方不写了,大概这个意思)

Person.h.h@interface Person : NSObject {        Room *_room;}@end.m- (void)setRoom:(Room *)room {        _room = room;}- (Room *)room {        return _room;}main.mint main(){        Person *p = [[Person alloc] init];        Room *r = [[Room alloc] init];        p.room = r;//重点理解一下这一句,内存表示情况如下    return 0;}

这里写图片描述

为什么这么说呢,是酱紫滴,我们来看一下p.room = r;究竟是怎么个过程

p.room = r不就是调用了[p setRoom:r];这个方法吗
在这个方法中,其实就是把r指向的地址赋值给了_room,那么也就是说此时_room也指向了room对象,所以要进行retain一下,使引用计数加1。

这里还要注意一个地方就是,为什么要先对_room 做一次release呢,想一下这种情况,p.room = r;这时,对r进行retain了吧,如果又做p.room = r2;此时,room不再指向r,但是却没有把对r指向对象的引用计数减1。就会造成对r指向对象的内存泄露。所以为了避免这种情况,在我们每次赋值时,先释放旧值,告诉以前指向的对象,我不用你了,然后再对新值retain,告诉新的对象,我现在用你了。恩,就酱。

- (void)setRoom:(Room *)room {        [room retain];        [_room release];        _room = room;}

更好的做法应该是这样

- (void)setRoom:(Room *)room {        if(_room  != room) {            [_room release];            _room = [room retain];        }}

那么如果这个时候,你释放了person对象,会使得此时只有r指向room对象,而room对象引用计数还为2,当执行[r release]时,room对象引用计数为1,并且一直为1,始终占用内存,造成内存泄露。所以正确的做法是,在释放person对象时,要在它的dealloc方法中释放掉room对象,即在 person.m文件中加上

- (void)dealloc {        [_room release];        _room = nil;        // 可以直接这样 self.room = nil;        [super dealloc];//这个注意是一定要加的,而一定加在最后面}

这个[_room release];方法,就是向_room指向的对象发送release消息。
这会明白了吗,就是说既然person已经被销毁了,那么他应该对别人负责,告诉别人不再需要他了,以便不需要的内存被及时回收,不会造成内存泄露。

0 0