内存管理(2)

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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值