内存管理之引用计数

注意以下都是针对MRC下的

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

比如:
Person *p = [[Person alloc] init];
此时内存状态是这样的。
内存管理之引用计数_第1张图片

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

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

Person.h
.h
@interface Person : NSObject {
        Room *_room;
}
@end

.m
- (void)setRoom:(Room *)room {
        _room = room;
}
- (Room *)room {
        return _room;
}

main.m

int main(){
        Person *p = [[Person alloc] init];
        Room *r = [[Room alloc] init];
        p.room = r;//重点理解一下这一句,内存表示情况如下
    return 0;
}

内存管理之引用计数_第2张图片

为什么这么说呢,是酱紫滴,我们来看一下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已经被销毁了,那么他应该对别人负责,告诉别人不再需要他了,以便不需要的内存被及时回收,不会造成内存泄露。

你可能感兴趣的:(Objective-C语法)