关于OC中引用计数问题

1:被release之后的引用计数 
// class1 仅仅是一个自定义类 没有任何方法和属性 
class1 * c1 = [[class1 alloc]init]; 
NSLog(@"c1的retainCount = %lu",(unsigned long)[c1 retainCount]); 

//输出结果为 1 


当一个对象的引用计数为1的时候,再被release 那么这个对象所在的内存就会被标记为回收(如同硬盘的格式化标记),但并不会执行 retaincount --; 因为已经是被标记的无用内存了没必要再操作,就少了一次内存操作,如果这是你调用 retaincount 当这个内存被重用之前是可以取值,但是如果已经被重用。那你就死了。


2:NSString *s = @"test";

NSLog(@"s:%d",[s retainCount]); // -1或2147483647(即UINT_MAX ( Maximum value an `unsigned int'))

因为"test"为字符串常量,系统不会收回,也不会对其作引用计数,即使我们对s如何retain或release。


NSString *s1 = [NSString stringWithString:@"test"];   --在xcode7中 系统自动提示 str为常量。

NSString *s2 = [NSString stringWithString:[NSString stringWithFormat:@"test,%d",1]];

NSLog(@"s1:%d",[s1 retainCount]); // 2147483647

NSLog(@"s2:%d",[s2 retainCount]); // 2

可以看到第一个为"常量"对象,其retainCount方法的实现返回的是maxIntValue。


 NSString *number =  [NSString stringWithFormat:@"test,%d",1];

    NSLog(@"retaincout = %ld",CFGetRetainCount((__bridge CFTypeRef)number));

retaincout = 2

nsstring对于引用计数来说比较特殊,不建议考虑。只需要注意书写规范即可。


3: NSArray的引用计数
NSArray *arr = [[NSArray alloc]init]; 
NSLog(@"arr的retainCount = %lu.",(unsigned long)[arr retainCount]); 
//输出结果为 2 

关于NSArray的,NSArray是不会像这样初始化的,NSArray本身就是不可变数组,这样初始化里面不就没有数据了吗,如果改为用initWithObject:它的retaincount就正常了。

总结:

  iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序。

   操作系统的内存管理分成堆和栈。


   在堆中分配的内存,都试用引用计数模式;在栈中则不是。


   NSString 定义的对象是保存在栈中,所以它没有引用计算。看一些书上说它的引用计算会是 fffffffff 最大整数,测试的结果显示它是- 1. 对该对象进行 retain 操作,不好改变它的 retainCount 值。


   MutableNSString 定义的对象,需要先分配堆中的内存空间,再初始化才能使用。它是采用引用计数管理内存的。对该对象做 retainCount 操作则每次增加一个。


   其实,引用计数是对内存区域的空间管理方式,是应从内存块的视角去看的。任何对象都是指向它的指针,有多少个指针指向它,就有多少个引用计算。

   如果没有任何指针指向该内存块了,很明显,该内存块就没有对象引用了,引用计算就是 0, 系统会人为该内存区域已经空闲,于是立即清理,也就是更新一下管理堆的链表中某个标示位。



引用计数

       Cocoa采用了引用计数(reference counting)机制,每一个对象有一个关联的“整数retainCount”用于记录对象的使用情况。对象被引用时retaincount+1,外部环境结束对象的使用后retainCount-1.当retaincount为0的时候,该对象被销毁。

        当我们使用alloc、new或者copy的我们需要销毁这个对象。release函数,只是将对象的retainCount值减1,并不是删除对象。当retainCount==0的时候,系统会发给对象一个dealloc消息,另外:千万不要手动调用dealloc,因为我们不知道何时,何地,何人还会使用该对象。应该老老实实依赖引用计数机制完成内存管理。

        释放对象所有权的函数除了release还有autorelease,这是一种延迟操作


自动释放池autoreleasepool

        自动释放池是NSAutoreleasePool的实例,其中包含了收到autorelease消息的对象。当一个自动释放池自身被销毁(dealloc)时,它会给池中每一个对象发送一个release消息(如果你给一个对象多次发送autorelease消息,那么当自动释放池销毁时,这个对象也会收到同样数目的release消息)。可以看出,一个自动释放的对象,它至少能够存活到自动释放池销毁的时候。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值