首页 > 代码库 > 黑马程序员-内存管理之autorelease和ARC机制

黑马程序员-内存管理之autorelease和ARC机制

一.autorelease

  之前我们都是手动release对象,但是有时候我们需要延迟release对象,这里我们就需要用到autorelease,系统会把当前对象放在当前的autorelease pool中,当autorelease pool销毁时,会把当前池子中的所有对象做一次release操作。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这些池子都是以栈结构的形式存在,在每一个Runloop结束时,当前栈顶的池子会被销毁,所有对象做一次release操作

1.autorelease的基本用法
1> 会将对象放到一个自动释放池中
2> 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
3> 会返回对象本身
4> 调用完autorelease方法后,对象的计数器不变

2.autorelease的好处
1> 不用再关心对象释放的时间
2> 不用再关心什么时候调用release

3.autorelease的使用注意
1> 占用内存较大的对象不要随便使用autorelease
2> 占用内存较小的对象使用autorelease,没有太大影响


4.错误写法
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];
}

5.自动释放池
1> 在iOS程序运行过程中,会创建无数个池子。这些池子都是以栈结构存在(先进后出)
2> 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池


6.自动释放池的创建方式
1> iOS 5.0前
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

[pool release]; // [pool drain];

2> iOS 5.0 开始
@autoreleasepool
{

}
下面是示例代码:

 1 #import <Foundation/Foundation.h> 2  3 @interface Person : NSObject 4 @property (nonatomic, assign) int age; 5  6 + (id)person; 7  8 + (id)personWithAge:(int)age; 9 10 @end
 1 #import "Person.h" 2  3 @implementation Person 4  5 + (id)person 6 { 7     return [[[self alloc] init] autorelease]; 8 } 9 10 + (id)personWithAge:(int)age11 {12     Person *p = [self person];13     p.age = age;14     return p;15 }16 17 - (void)dealloc18 {19     NSLog(@"%d岁的人被销毁了", _age);20     21     [super dealloc];22 }23 @end
1 #import "Person.h"2 3 @interface GoodPerson : Person4 5 @property (nonatomic, assign) int money;6 7 @end
#import "GoodPerson.h"@implementation GoodPerson@end
 1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 #import "GoodPerson.h" 4  5 int main() 6 { 7     @autoreleasepool { 8         Person *p = [Person personWithAge:100]; 9         10         11         GoodPerson *p2 = [GoodPerson personWithAge:10];12         13         p2.money = 100;14     }15     return 0;16 }

注意问题:

1.系统自带的方法里面没有包含alloc、new、copy,说明返回的对象都是autorelease的,例如以下2个例子。

NSString *str = @"123123";
NSString *str2 = [NSString stringWithFormat:@"age is %d", 10];


下面调用了对象方法,需要release操作
NSNumber *num = [[NSNumber alloc] initWithInt:10];

[num release];

2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象
1> 创建对象时不要直接用类名,一般用self
+ (id)person
{
  return [[[self alloc] init] autorelease];
}

二.ARC机制

ARC机制是IOS5所引入的,英文全称Automatic Reference Counting,自动引用计数,即ARC。有了ARC我们就不需要来手动操作内存管理的引用计数了,像retain,relesase,autorelease关键字都禁止使用。ARC全程帮我们管理内存,少了很多代码,也不用担心内存泄露。

ARC的特点:

1.ARC特点
1> 不允许调用release、retain、retainCount、autorelease
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)
* weak :成员变量是弱指针(适用于OC对象类型)
* assign : 适用于非OC对象类型
4> 以前的retain改为用strong

2.ARC的判断准则:只要没有强指针指向对象,就会释放对象。

下面代码是不使用ARC和使用ARC的区别。

创建一个Person类。

非ARC

 1 #import <Foundation/Foundation.h> 2  3 @class Dog; 4  5 @interface Person : NSObject 6  7 @property (nonatomic, retain) Dog *dog; 8  9 @property (nonatomic, retain) NSString *name;10 11 @property (nonatomic, assign) int age;12 13 @end
 1 #import "Person.h" 2  3 @implementation Person 4  5 - (void)dealloc 6 { 7     NSLog(@"Person is dealloc"); 8  9     [_dog release];10     [_name release];11     12     [super dealloc];13 }14 15 @end
 1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 #import "Dog.h" 4  5 int main() 6 { 7     Dog *d = [[Dog alloc] init]; 8     Person *p = [[Person alloc] init]; 9     p.dog = d;10     [p release];11     [d release];12     13     return 0;14 }

 

使用ARC后代码变成了如下:

 1 #import <Foundation/Foundation.h> 2  3 @class Dog; 4  5 @interface Person : NSObject 6  7 @property (nonatomic, strong) Dog *dog; 8  9 @property (nonatomic, strong) NSString *name;10 11 @property (nonatomic, assign) int age;12 13 @end
 1 #import "Person.h" 2  3 @implementation Person 4  5 // 如果要重写dealloc,禁止写最后的[super dealloc]; 6 - (void)dealloc 7 { 8     NSLog(@"Person is dealloc"); 9     10     // [super dealloc];11 }12 13 @end
 1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 #import "Dog.h" 4  5 int main() 6 { 7     Dog *d = [[Dog alloc] init]; 8     Person *p = [[Person alloc] init]; 9     p.dog = d;10 11     return 0;12 }

很明显的变化就是使用了ARC机制后禁止调用release、retain、retainCount、autorelease关键字,原来的retain用strong来代替,重写dealloc方法时禁止调用[super dealloc]

 

黑马程序员-内存管理之autorelease和ARC机制