Objective-C 基础知识之 (十六):内存管理原则一

内存管理

 

OC中的内存管理机制:引用计数

每个对象都有引用计数。理论上:当对象的引用计数为0时,系统会自动调用方法,销毁对象,回收内存。

在开发中,存在多个指针操作同一个对象。如果需要使用对象,不想出现对象提前被销毁的情况,需要增加这个对象的引用计数。

如果不再需要使用对象,减少相应的引用计数。

 

引用计数加1的实现:

alloc 引用计数加1   0 -> 1

Person * p =[[Person alloc] init]; //1

NSLog(@"%lu",p.retainCount);

Retain.count计算对象的引用次数,返回值NSUinteger。

       

retain 引用计数加1  在原有的基础上增加

 [p retain]; // 2

 NSLog(@"%lu", p.retainCount);

       

      

copy 引用计数加1

被拷贝对象的引用计数不变,新创建的对象的引用计数从0增加为1。

 

引用计数减1的实现:

release 引用计数减1  在原有的基础上减少

 [p release];

NSLog(@"%lu",p.retainCount); // 1

     

 [p release]; // 0

此时,系统销毁对象,回收内存。

指针p被称为野指针。不应该再使用指针p操作原对象调用方法

NSLog(@"%lu",p.retainCount);

       

autorelease 引用计数减1 在未来的某个时刻减1

p = nil; // 空指针

 

如果想安全使用对象,可以通过对象调用retain方法,增加对象的引用计数。 持有(拥有)对象。

当不再需要使用对象时,要通过对象调用release方法,减少对象的引用计数。

在一段代码内,保证引用计数的增加和减少平衡,保证对象的引用计数最终可以减到0.

 

对象的引用计数增减不平衡,会造成的情况:内存泄露、野指针异常。

内存泄露:增加的次数 > 减少的次数

Person * p =[[Person alloc]init];  // 1

 [p retain]; // 2

 [p release];// 1

当main函数执行结束后,指针p被销毁,无法再通过指针找到对象,对象无法被销毁,内存空间无法释放

       

野指针异常:增加的次数 < 减少的次数

Person * p =[[Person alloc]init];  // 1

 [p release];// 0  这句话执行结束后,对象已经被销毁.

       

p = nil; 在OC中将指针置为nil,可以避免野指针。

[p release];// -1 这句话中的p是野指针,过度释放。

 

当对象的引用计数应该减为0时,对象自动调用dealloc方法,销毁对象,释放内存。

- (void)dealloc

{

    NSLog(@"Person对象将要被销毁");

   

    [super dealloc]; //这句话写在最后。

}


Autorelease

在MRC下使用NSAutoreleasePool类

   

创建自动释放池

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  

两句话之间的位置,属于自动释放池内部

    Person * p = [[Person alloc] init];

[p retain];

如果对象P在自动释放池pool内部,调用autorelease方法,那么自动释放池会记录对象将要调用release方法的信息。

对象在自动释放池内部调用N次autorelease方法。那么,自动释放池会记录N次。

 [p autorelease];

 [p autorelease];

NSLog(@"自动释放池未被销毁:%lu", p.retainCount);

   

销毁自动释放池

[pool release];

   

autorelease什么时候实现引用计数减1?

管理这个对象的自动释放池被销毁时,在自动释放池内部调用autorelease方法的对象,全部会执行一次release方法

NSLog(@"自动释放池未被销毁:%lu", p.retainCount); 

自动释放池销毁方法      [pool release] 或 [pool drain]

 

 

MRC、ARC  下的autorelease   

@autoreleasepool

 

Person * p =[[Person alloc] init];

 [p retain];

NSLog(@"%lu",p.retainCount);

   

@autoreleasepool {

自动释放池内部

[p autorelease];

NSLog(@"自动释放池未被销毁 %lu", p.retainCount);

    }

NSLog(@"自动释放池被销毁 %lu", p.retainCount);

自动释放池可以自己创建,也可以是系统的方法实现内部创建


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值