OC语言 - 内存管理:alloc | retain | release
内存管理
1 - MRC(Manual Reference Count)人工引用计数:内存的开辟和释放由程序代码进行控制;ARC(Automatic Reference Count)自动引用计数。它并不是自动管理内存,而是编译器帮助程序员默认加了释放代码
2 - 在 C 语言中使用 malloc 和 free 进行堆内存的创建和释放,堆内存只需要正在使用和销毁两个状态;两个以上的指针使用同一块内存,C 语言是无法记录内存使用者的个数的
引用计数
1 - alloc: 创建对象并获取对象所有权,引用计数从 0 变为 1
2 - retain:引用计数在原来的基础上 +1,并获得对象的所有权
3 - copy : 拷贝出一个新副本,将副本的引用计数置 1,并拥有副本的所有权
4 - release : 释放对象,引用计数立即 -1,并释放对象的所有权
5 - autorelease: 未来的某一时刻引用计数 -1,获取对象存在(不持有)并放弃对象所有权,可理解为 release 的自动延迟
注:避免频繁使用 autorelease
alloc | retain | release
1 - 代码示例:alloc、retain 和 release
// - Student.h
1 #import <Foundation/Foundation.h> 2 @interface Student : NSObject 3 4 5 @end
// - Student.m
1 #import "Student.h" 2 3 @implementation Student 4 5 -(void)dealloc{ 6 NSLog(@"%@已经销毁",self); 7 [super dealloc]; 8 } 9 10 @end
// - main
1 #import <Foundation/Foundation.h> 2 #import "Student.h" 3 4 int main(int argc, const char * argv[]) { 5 6 // alloc 7 Student *student = [[Student alloc] init];// 1 8 9 10 // retain 11 [student retain];// 2 12 [student retain];// 3 13 14 // release 15 [student release];// 2 16 [student release];// 1 17 18 19 [student release];// 1 20 // 此时 release 后则触发 dealloc,但是 retainCount 并不会马上回到 0,且指针变量本身也不会自动置 nil,依旧指向原来的地址,所谓的悬垂指针 21 NSLog(@"%p",student);// 验证:会打印出原地址 22 23 student = nil; 24 [student release];// 空指针可无限制地 release,没有实际意义 25 NSLog(@"%lu",[student retainCount]);// 0 dealloc 被触发后必须手动置 nil,这样 retainCount 才会归 0 26 27 // 如果对象被销毁后且没有手动置 nil,继续使用该对象则 crash 28 [student release];// crash 29 30 return 0; 31 }
小结
1 - 当一个所有者(其可以是任何一个 Objective-C 对象)做了以下某个动作时,它就拥有了对一个对象的所有权
① 如果创建或者复制某个对象时,则拥有了该对象的所有权:alloc、allocWithZone:、copy、copyWithZone:、mutableCopy、mutableCopyWithZone:
② 如果没有创建对象,而是将对象保留使用,同样拥有该对象的所有权:retain
③ 如果你拥有了某个对象的所有权,在不需要某一个对象时,需要释放它们:release、autorelease