Objective-C的MRC手动内存管理——自动释放

内存管理对于Objective-C来说真是一个复杂的问题,很多时候我们要弄清楚某个对象的所有权归属并不容易,由此造成难以找到合适的释放对象的方法。

但Cocoa中有一个自动释放池的概念给我们提供了便利。

 

0x01 自动释放池的创建

autorelease

NSObject类提供了一个autorelease方法,该方法预先设定了一条会在未来某个时间发送的release消息,其返回值是接收这条消息的对象:

- (id) autorelease;

当给一个对象发送autorelease消息时,实际上是将该对象添加到了自动释放池中。

当自动释放池被销毁时,会向该池中的所有对象发送release消息。

 

NSAutoreleasePool对象

使用NSAutoreleasePool对象可以创建一个自动释放池,在创建和释放NSAutoreleasePool对象之间的代码都会使用该池:

NSAutoreleasePool *pool;
pool = [NSAutoreleasePool new];
//Coding in here...
[pool release];

 

0x02 自动释放池的工作原理

在我们创建基于Foundation的项目时,其实编译器已经自动帮我们创建了@autorelease的自动释放池:

#import 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

1、当我们把代码写在@autoreleasepool的花括号里时,所有的代码都是自动释放的;

2、任何在@autoreleasepool的花括号定义的变量,在括号外是无法使用的,类似于C语言的数据有效范围;

3、iOS 5.0之后已经淘汰使用NSAutoreleasePool对象创建自动释放池的方法,因为@autoreleasepool更直观,而且Objective-C语言创建和释放内存的能力远在我们之上。

4、autorelease只是把对象扔到自动释放池里面(延迟了对象被销毁的时间),并不可以改变对象的计数器;

5、改变计数器只有retain和release两种方法;

6、autorelease和release不能同时存在:

autoreleasepool{
      Car *c = [[[Car alloc] init] autorelease];
      [c release];
}

//错误!!!
//对对象执行二次释放会出现野指针错误!!!

7、autoreleasepool是以栈结构存在的,栈结构的特点就是先进后出;

8、autorelease的缺点是不能精确控制对象被销毁的时间,内存处理效率低(适用于占用内存比较小的对象,对象里面包含的属性主要是基本数据类型)。如果是在一个循环中出现大量的迭代,必须自己在循环中创建一个自动释放池来定期清理:

NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init]; 

int i;

for (i = 0; i < 1000000; i++) {
    id object = [someArray objectAtIndex: i]; 
    NSString *desc = [object descrption];

// and do something with the description 
    if (i % 1000 == 0) {
     [pool release];
     pool = [[NSAutoreleasePool alloc] init];
     }
}
[pool release];

9、在调用函数的过程中自动释放池不会被销毁,程序不会随即销毁自动释放池,因此不必保留使用的每一个对象;

10、自动释放池被清理的时间是完全确定的:要么在代码中自己手动销毁,要么是使用APPKit时在时间循环结束时销毁。

 

你可能感兴趣的:(Objective-C,Objective-C基础教程)