引用计数式内存管理的思考方式
- 自己生成的对象,自己持有。
- 非自己生成的对象,自己也能持有。
- 不再需要自己持有的对象时释放。
- 非自己持有的对象无法释放。
对象操作 | Objective-C 方法 | 引用计数值 |
---|---|---|
生成并持有对象 | alloc/new/copy/mutableCopy 等方法 | +1 |
持有对象 | retain 方法 | +1 |
释放对象 | release 方法 | -1 |
废弃对象 | dealloc 方法 | -1(归零) |
引用计数式内存管理的实现方式
NSObject 类的 alloc 方法执行时所调用的方法和函数有:
- +alloc
- +allocWithZone:
- class_createInstance
- calloc
retainCount 方法执行时所调用的方法和函数有:
- -retainCount
- __CFDoExternRefOperation
- CFBasicHashGetCountOfKey
retain 方法执行时所调用的方法和函数有:
- -retain
- __CFDoExternRefOperation
- CFBasicHashAddValue
release 方法执行时所调用的方法和函数有:
- -release
- __CFDoExternRefOperation
- CFBasicHashRemoveValue( CFBasicHashRemoveValue 返回 0 时, -release 调用 dealloc )
由上可知内存管理的实现是通过散列表来管理引用计数的。
autorelease 的使用
- 生成并持有 NSAutoreleasePool 对象;
- 调用已分配对象的 autorelease 实例方法;
- 废弃 NSAutoreleasePool 对象。
1 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
ARC 内存管理修饰符
__strong
修饰符:默认的所有权修饰符,表示对对象的“强引用”。持有强引用的变量在超出其作用域时被废弃。引用的对象会随之释放。__autoreleasing
修饰符:在 ARC 有效时,用@autoreleasepool
块代替 NSAutoreleasePool 类,用附有__autoreleasing
修饰符的变量替代 autorelease 方法。__unsafe_unretained
修饰符:在 iOS4 中代替__weak
。__weak
修饰符:两个对象互相引用会出现“循环引用”的问题,引起内存泄露,即应当废弃的对象在超出其生存周期后继续存在。弱引用不能持有对象实例。在持有某对象的弱引用时,若该对象被废弃,则此弱引用将自动失效且处于赋 nil 值的状态。使用附有__weak
修饰符的变量,即是使用注册到 autoreleasepool 中的对象,并且最好先暂时赋值给附有__strong
修饰符的变量后再使用。1
2
3id __weak o = obj;
id tmp = o;
NSLog(@"1 %@", tmp);
ARC 内存管理规则
- 不能使用 retain / release / retainCount / autorelease
- 不能使用 NSAllocateObject / NSDeallocateObject
- 须遵守内存管理的方法命名规则
- 不能显式调用 dealloc
- 使用
@autoreleasepool
块代替 NSAutoreleasePool - 不能使用 NSZone
- 对象型变量不能作为 C 语言结构体的成员
- 显式转换
id
和void *