Objective - C基础: 第五天 - 7.autorelease的基本认识

前面我们学了OC内存管理的手动引用计数, 一个alloc, 一个release, 对象的释放由我们自己所决定, 在这里应该会有人问, 这样子运用手动引用计数好累, 有没有简单一点的方法, 答案肯定是有的, 现在我们就来看看第一个简单一点的方法, autorelease方法.

首先我们来看看以前所写的例子:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, assign)int age;

@end

#import "Person.h"

@implementation Person

- (void)dealloc
{
    NSLog(@"Person对象被释放了.");
    
    [super dealloc];
}

@end
#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[])
{
    Person *p = [[Person alloc] init];
    
    p.age = 10;
    
    [p release];
    return 0;
}

打印出来的结果:

2015-01-27 16:39:19.419 08.autorelease基本认识[6599:712028] Person对象被释放了.

这个就是我们之前所写的例子, 在main()函数中, 我们必须得把release写在各种操作之后, 否则就会出现野指针错误, 这个我们在前面就已经知道了, 虽然这样子做可以非常的精准, 但很累人, 所以autorelease出现了, 我们看看修改后的例子:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[])
{
    
    @autoreleasepool
    {
        Person *p = [[Person alloc] autorelease];
        
        p.age = 10;
    }
    
    return 0;
}

打印出来的结果:

2015-01-27 16:43:29.602 08.autorelease基本认识[6619:713881] Person对象被释放了.

使用了autorelease一样可以让对象被释放~~这样子我们在main()函数里写对象的时候就再去担心对象没有被release.

但注意一下, autorelease的作用并不是释放对象, 只是建造一个自动内存池, 把对象放进去, 只要内存池被销毁, 对象才会被release, 并不是直接释放对象.

还有, autorelease是可以多重嵌套使用的, 比如:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[])
{
    
    @autoreleasepool
    {
        Person *p = [[Person alloc] autorelease];
        
        p.age = 10;
        
        @autoreleasepool {
            Person *p1 = [[Person alloc] autorelease];
            
            p1.age = 20;
        }
    }
    
    return 0;
}

打印出来的结果:

2015-01-27 17:19:34.054 08.autorelease基本认识[6672:721475] Person对象被释放了.
2015-01-27 17:19:34.055 08.autorelease基本认识[6672:721475] Person对象被释放了.

注意一点, autorelease使用的场景一般是在占用内存比较小的对象下使用, 比如一个对象里面几乎都是基本数据类型的, 如果是占用内存比较大的对象, 最好还是使用手动引用计数, 否则会引起内存泄漏.

autorelease的错误写法:

1> alloc之后调用了autorelease,又调用release

 @autoreleasepool
 {
    // 1
    Person *p = [[[Person alloc] init] autorelease];
 
    // 0
    [p release];
 }

2> 连续调用多次autorelease

 @autoreleasepool
 {
    Person *p = [[[[Person alloc] init] autorelease] autorelease];
 }

下面我们来总结一下:

1.autorelease的基本用法

1> 会将对象放到一个自动释放池中

2> 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

3> 会返回对象本身

4> 调用完autorelease方法后,对象的计数器不变

2.autorelease的好处

1> 不用再关心对象释放的时间

2> 不用再关心什么时候调用release

3.autorelease的使用注意

1> 占用内存较大的对象不要随便使用autorelease

2> 占用内存较小的对象使用autorelease,没有太大影响

4.自动释放池

1> 在iOS程序运行过程中,会创建无数个池子。这些池子都是以栈结构存在(先进后出)

2> 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

好了, 这次我们就讲到这里, 下次我们继续~~