6.【掌握】单个对象内存管理
1、【掌握】避免使用僵尸对象的方法
为了防止不小心调用了僵尸对象,可以将对象赋值nil(对象的空值)
- 给空指针发消息是没有任何反应的。
Student *s = [[Student alloc] init]; [s release]; s = nil; // 打印对象的引用计数器值 NSLog(@"%lu",[s retainCount]);
- 给空指针发消息是没有任何反应的。
2、【掌握】对象的内存泄露
1.retain和release的个数不匹配,导致内存泄露。
2.对象使用的过程中被赋值了nil,导致内存泄露
3.在函数或者方法中不当的使用retain 或者 release 造成的问题
7.【掌握】多个对象内存管理(野指针)
- 单个对象的内存管理,看起来非常简单。
如果对多个对象进行内存管理,并且对象之间是有联系的,那么管理就会变得比较复杂。
其实,多个对象的内存管理思路,跟管理游戏房间类似:
- 如:劲舞团,LOL
// 1、创建玩家对象
Gamer *game = [[Gamer alloc] init];
// 2、创建房间对象
Room *room = [[Room alloc] init];
// 3、让玩家进入房间
game.room = room;
// 4、释放房间对象
[room release];
// 5、输出玩家的房间
NSLog(@"玩家的房间是:%@",game.room);
- 此时,会报野指针错误。
8、【掌握】多个对象内存管理
- 解决方案:在使用房间时,对房间进行一次release。
// 声明类
@interface Gamer : NSObject
{
Room *_room;
}
- (void)setRoom:(Room *)room;
- (Room *)room;
// 实现类
@implementation Gamer
- (void)setRoom:(Room *)room
{
[room retain];
_room = room;
}
- (Room *)room{
return _room;
}
- (void)dealloc
{
NSLog(@"玩家被释放");
[super dealloc];
}
@end
// main函数实现
// 1、创建玩家对象
Gamer *game = [[Gamer alloc] init];
// 2、创建房间对象
Room *room = [[Room alloc] init];
// 3、让玩家进入房间
game.room = room;
// 4、释放房间对象
[room release];
// 5、输出玩家的房间
NSLog(@"玩家的房间是:%@",game.room);
问题:房间无法被释放了怎么办?
解决方法:
- 在对象被释放时,要把该对象的所有对象类型的成员变量在dealloc当中进行释放:
@implementation Gamer
- (void)dealloc
{
[_room release];
NSLog(@"玩家被释放");
[super dealloc];
}
@end
- 需求:让玩家反复进入这个房间。
int main(int argc, const char * argv[]) {
@autoreleasepool {
Gamer *g = [Gamer new];
Room *r = [Room new];
g.room = r;
g.room = r;
g.room = r;
[g release];
[r release];
}
return 0;
}
问题:房间对象无法被释放,怎么办?
解决方案:判断新进房间与之前是否是同一个房间。
- (void)setRoom:(Room *)room
{
if (_room != room) {
[room retain];
_room = room;
}
}
- 总的来说,有以下几点规律:
- 1)只要还有人使用某对象,那么这个对象就不会被回收。
- 2)只要想要使用1个对象,那么就让对象的引用计数器+1。
- 3)当不再使用这个对象时,就让对象的引用计数器-1。
9、【掌握】set方法内存管理
- 需求:
- 1、让玩家换房间,进入1号房间后,再进入2号房间
// 实现玩家类
@implementation Gamer
- (void)setRoom:(Room *)room
{
[_room release];
_room = [room retain];
}
- (Room *)room{
return _room;
}
- (void)dealloc
{
[_room dealloc];
NSLog(@"玩家被释放");
[super dealloc];
}
@end
int main(){
// 1、创建玩家对象
Gamer *game = [[Gamer alloc] init];
// 2、创建房间对象
Room *room = [[Room alloc] init];
room.no = 1;
Room *room1 = [[room alloc] init];
room.no = 2;
// 3、让玩家进入房间
game.room = room;
game.room = room1;
// 4、释放房间对象
[room release];
// 5、释放玩家对象
[game release];
return 0;
}
- 问题:房间对象再次无法被释放
- 解决方案:
- (void)setRoom:(Room *)room
{
if (_room != room)
{
// 释放旧房间
[_room release];
[room retain];
_room = room;
}
}
- 总结:
- 1、set方法的内存管理
- (void)setRoom:(Room *)room
{
if(_room != room){
[_room release];
_room = [room retain];
}
}
- 2、dealloc方法内存管理
- (void)dealloc
{
// 当玩家不在了,代表不用房间了
// 对房间进行一次release
[_room release];
// 重写dealloc方法,必须在最后调用父类的dealloc方法
[super dealloc];
}
- 常见错误写法
- 会引发内存泄露
objc
gamer.room = [[Room alloc] init];
[[Room alloc] init].no= 10;