面试题答案
一键面试ARC(自动引用计数)环境下
- 键的内存管理:
- 字典要求键对象遵循
NSCopying
协议。当向字典中添加键值对时,字典会对键进行拷贝(copy
操作)。如果键是不可变对象(如NSString
、NSNumber
等),拷贝操作是浅拷贝,即只是增加引用计数,因为不可变对象的内容不会改变。如果键是可变对象,会进行深拷贝,创建一个新的不可变副本。ARC会自动管理键对象的引用计数,当字典不再使用该键(例如字典被释放),键对象的引用计数会相应减少,当引用计数降为0时,ARC会自动释放键对象的内存。
- 字典要求键对象遵循
- 值的内存管理:
- 字典会对值对象保持强引用(
strong
引用)。当向字典中添加值时,值对象的引用计数增加。当从字典中移除值或者字典被释放时,值对象的引用计数减少。当值对象的引用计数降为0时,ARC会自动释放值对象的内存。
- 字典会对值对象保持强引用(
- 自定义对象作为值:
- 如果自定义对象作为字典的值,开发者无需手动管理其内存释放。只要字典对该自定义对象保持强引用,该对象就不会被释放。当字典不再持有该自定义对象(如移除值或字典本身被释放),ARC会自动处理自定义对象的内存释放,只要没有其他强引用指向该自定义对象,它就会被释放。需要注意的是,自定义对象内部如果有对其他对象的引用,要确保这些引用的内存管理得当,避免循环引用。例如,如果自定义对象A持有对字典的引用,而字典又持有对自定义对象A的引用,这就会形成循环引用,此时可以使用弱引用(
weak
)或无主引用(unowned
)来打破循环引用。
- 如果自定义对象作为字典的值,开发者无需手动管理其内存释放。只要字典对该自定义对象保持强引用,该对象就不会被释放。当字典不再持有该自定义对象(如移除值或字典本身被释放),ARC会自动处理自定义对象的内存释放,只要没有其他强引用指向该自定义对象,它就会被释放。需要注意的是,自定义对象内部如果有对其他对象的引用,要确保这些引用的内存管理得当,避免循环引用。例如,如果自定义对象A持有对字典的引用,而字典又持有对自定义对象A的引用,这就会形成循环引用,此时可以使用弱引用(
MRC(手动引用计数)环境下
- 键的内存管理:
- 同样,字典要求键对象遵循
NSCopying
协议。当向字典添加键值对时,字典会对键进行拷贝(copy
操作)。如果键是不可变对象,进行浅拷贝,需要开发者手动调用release
方法来减少引用计数。如果键是可变对象,会进行深拷贝,开发者同样需要在适当的时候调用release
方法来释放键对象的内存。例如,当字典被释放或者键从字典中移除时,开发者要确保键对象的引用计数被正确减少,避免内存泄漏。
- 同样,字典要求键对象遵循
- 值的内存管理:
- 字典对值对象保持强引用。当向字典添加值时,开发者需要手动调用
retain
方法来增加值对象的引用计数。当从字典中移除值或者字典被释放时,开发者需要手动调用release
方法来减少值对象的引用计数。如果没有正确调用retain
和release
方法,会导致内存泄漏或悬空指针问题。
- 字典对值对象保持强引用。当向字典添加值时,开发者需要手动调用
- 自定义对象作为值:
- 当自定义对象作为字典的值时,开发者需要手动管理其内存。在将自定义对象添加到字典时,要调用
retain
方法增加引用计数。当从字典中移除自定义对象或者字典被释放时,要调用release
方法减少引用计数。同时,在自定义对象的生命周期内,如果有对其他对象的引用,也需要手动管理这些引用的retain
和release
操作,避免内存泄漏和悬空指针。例如,如果自定义对象内部有对其他对象的强引用,在自定义对象的dealloc
方法中要确保对这些引用对象调用release
方法。并且要特别注意避免循环引用,例如可以通过在适当的地方使用release
来打破循环引用,如在对象A的dealloc
方法中对持有对象B的引用调用release
,对象B在dealloc
方法中对持有对象A的引用调用release
。
- 当自定义对象作为字典的值时,开发者需要手动管理其内存。在将自定义对象添加到字典时,要调用