面试题答案
一键面试对象的内存分配和释放
- 分配:
- 在Objective - C中,使用
alloc
方法为对象分配内存。例如,假设有一个自定义类MyClass
,可以这样分配内存:
MyClass *obj = [[MyClass alloc] init];
alloc
方法会在堆上为对象分配足够的内存空间来存储对象的实例变量以及相关的元数据。它返回一个指向新分配内存区域的指针,但此时对象的实例变量还未初始化。- 通常会紧接着调用
init
方法来初始化对象的实例变量,使其处于一个可用的状态。init
方法会返回一个已初始化的对象实例。
- 在Objective - C中,使用
- 释放:
- 在ARC(自动引用计数)出现之前,手动管理内存时,对象使用完毕后需要调用
release
方法来释放其占用的内存。例如:
[obj release];
- 当对象的引用计数降为0时(引用计数概念见下),对象所占用的内存会被系统回收,归还给堆内存池,以便后续重新分配使用。
- 在ARC(自动引用计数)出现之前,手动管理内存时,对象使用完毕后需要调用
引用计数的作用
- 概念:每个Objective - C对象都有一个引用计数(reference count),它是一个整数值,记录了指向该对象的引用(指针)的数量。
- 作用:
- 引用计数用于跟踪对象是否仍在被使用。当有新的指针指向对象时,引用计数会增加(通常通过
retain
方法,ARC下自动处理);当指针不再指向对象(如指针被赋值为nil
或超出作用域),引用计数会减少(通常通过release
方法,ARC下自动处理)。 - 当对象的引用计数变为0时,意味着没有任何指针指向该对象,表明该对象不再被使用,系统可以安全地释放其占用的内存,从而避免内存泄漏。例如:
MyClass *obj1 = [[MyClass alloc] init];// obj1引用计数为1 MyClass *obj2 = obj1;// obj1引用计数增加到2 [obj1 release];// obj1引用计数减为1,因为obj2还指向它 obj2 = nil;// obj1引用计数减为0,对象内存被释放
- 引用计数用于跟踪对象是否仍在被使用。当有新的指针指向对象时,引用计数会增加(通常通过
ARC的工作原理
- 自动插入内存管理代码:ARC是Xcode 4.2引入的一项功能,它自动管理Objective - C对象的内存。编译器会在编译时自动在合适的位置插入
retain
、release
和autorelease
等内存管理方法。 - 作用域规则:
- 当对象被创建时,编译器会插入
retain
操作来增加其引用计数。例如:
MyClass *obj = [[MyClass alloc] init];// 编译器自动在合适位置插入retain操作,使对象引用计数增加
- 当对象的指针超出其作用域时,编译器会插入
release
操作来减少其引用计数。例如:
{ MyClass *obj = [[MyClass alloc] init]; // 代码块结束,obj超出作用域,编译器自动插入release操作,引用计数减少 }
- 当对象被创建时,编译器会插入
- autorelease池:ARC仍然使用
autorelease
池来延迟对象的释放。例如,当一个对象在方法中被返回时,编译器可能会将其发送autorelease
消息,将对象放入最近的自动释放池中。当自动释放池被排空时,池中的对象会收到release
消息,引用计数相应减少。在iOS应用中,主线程有一个隐含的自动释放池,会在每次事件循环结束时排空,以确保及时释放不再使用的对象。
通过ARC,开发者无需手动编写繁琐的内存管理代码,大大减少了因内存管理不当导致的内存泄漏和悬空指针等问题,提高了开发效率和代码的稳定性。