黑马程序员-内存管理之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)age
11 {
12     Person *p = [self person];
13     p.age = age;
14     return p;
15 }
16
17 - (void)dealloc
18 {
19     NSLog(@"%d岁的人被销毁了", _age);
20
21     [super dealloc];
22 }
23 @end
1 #import "Person.h"
2
3 @interface GoodPerson : Person
4
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]

时间: 2024-12-15 01:43:45

黑马程序员-内存管理之autorelease和ARC机制的相关文章

黑马程序员----内存管理之四——《autorelease自动释放池》

内存管理之四——autorelease自动释放池 1.autorelease的基本使用 此对象方法会将对象放到一个自动释放池内: 当自动释放池被销毁时,就会对池子内的所有对象做一次release操作: 此方法会返回对象本身: 调用完此方法后,对象计数器的值不变,只有到自动释放池被销毁时才会对对象做一次release操作: 2.autorelease的好处 不用在关心对象被销毁的时间: 不用关心什么时候调用release操作: 3.autorelease的使用注意 占用内存较大的对象不要随便使用a

黑马程序员----内存管理之二《多对象的内存管理》

内存管理之二——<多对象的内存管理> 1.多对象的内存管理方式: 只要有人使用了这个对象,这个对象就不能被销毁: 只要你想使用这个对象,就让这个对象的引用计数器的值+1(让对象做一次retain操作): 当你不再使用这个对象,就让这个的对象的引用计数器的值-1(让对象做一次release操作): 谁alloc,谁就release: 谁retain,谁就release: 2.内存管理的代码规范: 只要调用了alloc必须有release/autorelease set方法的代码规范: 1.基本数

黑马程序员----内存管理一《基本使用》

内存管理 1.为什么要进行内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的: 当app所占用的内存较大时,系统就会发出内存警告,这时就的回收一些不需要使用的内存空间.比如:回收一些不需要的对象,变量等: 内存管理的范围:任何继承了NSObject的对象,对其他基本数据类型(int.char.float.double.struct.enum等)无效: 2.内存的基本结构 每个OC对象内部都有一个自己的引用计数器,是一个整数,表示:对象被调用的次数:即:有多少人正在使用这个OC对

黑马程序员-内存管理之set方法内存管理

一.set方法内存管理 当一个对象拥有另一个对象的属性时,需要在set方法对当前所拥有的对象做retain操作,因为你的属性是指向了另一个对象,需要让另一个对象知道有单元在使用我. 但是这样写的话不够完善,会出现新的问题.如果对象属性之前已经指向了某一个对象了,此时再传进来一个新的对象,属性指针就指向了新的对象,然后retain了新的对象,但是旧的对象此时并没有人工release过,需要release一下.还有一个问题就是在release旧对象,retain新对象之前要做一个判断,判断一下此时拥

黑马程序员-内存管理

一. OC的内存管理的过程 OC为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc. for example: 1.对象在完成创建的同时,内部会自动创建一个引用计数器,这个计数器,是系统用来判断是否回收对象的唯一依据,当我们的引用计数retainCount = 0的时候,系

黑马程序员----内存管理之五《ARC-自动引用计数》

内存管理之五<ARC-Automatic Reference Counting> 1.ARC概念 ARC是Automatic Reference Counting---自动引用计数. ARC是一种编译器特性,并不是java中得垃圾回收,java中的垃圾回收是运行时特性: ARC的判断准则:只要没有强指针指向对象,就会释放对象: 2.ARC的特点 不允许调用release.retain.retainCount: 允许重写dealloc方法,但是重写时不用再调用父类的dealloc方法 即 [su

黑马程序员----内存管理之三——《@property的内存管理》

内存管理之三——<@property的内存管理> 1.@property中与setter内存管理相关的参数 retain : release旧值,retain新值(适用于OC对象类型): assign : 直接赋值,(默认,适用于非OC对象类型): copy  : release旧值,copy新值: 2.@property中是否生成setter的参数 readonly  : 只会生成getter的声明和实现: readwrite : 同时生成setter和getter的声明和实现: 3.@pr

黑马程序员-内存管理之引用计数器

1.引用计数器 每种语言都有自己的内存管理机制,当然OC也不例外.当一个对象创建的时候,系统在堆中给这个对象分配了一块存储区域,这个对象被栈中的对象指针所指向,当没有任何指针指向这个对象的时候,系统怎么释放这块对象内存呢?OC中是用引用计数器来实现的.每一个对象拥有一个引用计数器(占四个字节),当对象被创建时,自带的引用计数器的值就为1了.给对象发送retain消息时,对象的引用计数器就做+1操作,表示有指针拥有这个对象,发送release消息时引用计数器做-1操作,表示某个指针不在拥有这个对象

黑马程序员 内存管理之proterty,autorelease

#import <Foundation/Foundation.h> @interface Person : NSObject { Book * _book; int _age; } /* oc对象 [email protected]能制动生成setter和getter方法 2.retain告诉编译器自动生成setter里的retain 3.atomic:低性能(默认情况下) nonatomic:高性能 */ @property (nonatomic, retain) Book *book; /