Object-C 指针 和 C 指针的相互转换 与ARC 并验证__bridge关键字的作用

引用计数器


1.引用计数器,是伴随对象的产生而产生的。
当我们执行下面语句的时候,它就产生了一个对象,并且默认该对象的引用计数器为1:
        id obj = [[NSObject alloc] init];
        NSLog(@"obj retainCount=%lx", [obj retainCount]);


输出结果: 
2014-07-29 18:32:59.346 Test_ARC_bridge[1127:303] obj retainCount=1
2.当我们在上面的代码加上另外一些代码时,如下(在ARC无效的情况下运行):        id obj = [[NSObject alloc] init];
        void *p =obj;
        [(id)p retain];  
        NSLog(@"p retainCount=%lx", [(id)p retainCount]);
        NSLog(@"obj retainCount=%lx", [obj retainCount]);


 
 
输出结果:
2014-07-29 18:26:49.324 Test_ARC_bridge[1100:303] p retainCount=2
2014-07-29 18:26:49.327 Test_ARC_bridge[1100:303] obj retainCount=2
分析上面代码:
	void *p =obj;
        [(id)p retain];//retainCount+1
 
这两句,相当与将p指针指向了obj对象,然后再将它的引用计数器+1,也就是等于2. 所以, (id)p  obj他们指向的是同一个对象,固他们的引用计数器值是一样的。

__bridge、__birdge_retained与__bridge_transfer

1.当我们在ARC有效的情况下运行下面代码:
id obj = [[NSObject alloc] init];
        void *p =obj;
你会发现在,ARC有效的情况下,编译器不允许你隐式的将Object-C 指针转换成C指针,即有如下错误提示:



2.__bridge 

查阅相关文档,我们可以用 __bridge  关键字来解决这一问题,修改代码如下:
        id obj = [[NSObject alloc] init];
        void *p =(__bridge void *)obj;
        NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj));
编译通过,输出结果:
2014-07-29 19:07:16.807 Test_ARC_bridge[1296:303] obj retainCount=1 //即P指针指向的该实体仍然是有效的
注意:在使用ARC的时候,编译器不在允许我们明确调用retainCount函数了,使用会报错滴!(因为, ARC模式就是不需要你关心引用计数

3.__bridge_retained
修改代码,使用__bridge_retained关键字代替__bridge关键字:
        id obj = [[NSObject alloc] init];
        void *p =(__bridge_retained void *)obj;
        NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj));

输出结果:
2014-07-29 19:18:04.187 Test_ARC_bridge[1315:303] obj retainCount=2

结合2和3两点,我们知道__bridge 与__bridge_retained的区别是,对象又有权的不同。即__bridge关键字,不对对象的引用计数器进行任何处理,而__bridge_retained
关键字则会让对象的引用计数器+1。同理,我们也可以推断出__bridge_transfer关键字是否同样对对象的所有权做了某些处理呢?

4.__bridge_transfer

修改代码,验证__bridge_transfer关键字的作用:
        id obj = [[NSObject alloc] init];
        void *p =(__bridge_retained void *)obj;
        NSLog(@"obj retainCount=%x", _objc_rootRetainCount(obj));
       id objOther= (__bridge_transfer id)p;
        NSLog(@"objOther retainCount=%x", _objc_rootRetainCount(objOther));

输出结果:
2014-07-29 20:20:55.984 Test_ARC_bridge[1723:303] obj retainCount=2
2014-07-29 20:20:55.987 Test_ARC_bridge[1723:303] objOther retainCount=2

结果很让人意外啊:为什么还是2?

以上代码和结论只提供参考,个人水平有限,不一定准确。在此也是为了做个笔记,方便以后翻阅时能解决该疑惑!
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

参考其他文章引用过来的结论:

对象所有权策略是基于引用计数实现的

对象所有权的策略是通过引用计数——通常叫做retain count实现的。每一个对象有一个retaincount变量。

1.创建对象后,它的retaincount是1

2. retain之后,retain count +1

3.release之后 retain count -1 

4.autorelease之后,在自动释放池最后-1

5.对象的retain count减少到0的时候,对象被销毁。

【重要】

不要显式调用对象的retainCount,结果往往具有误导性,作为开发者可能不了解框架式如何对对象retain的。在调试内存管理中,你应该只关注确保你的代码遵循所有权规则。





个人初步结论:

1. __bridge_retained 告诉ARC 一旦__bridge_retained转换完成,ARC就不用在负责释放该对象了,使用者需要手动释放,即使用者拥有该对象的持有权。相当于:
 
   
id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];
//即当obj变量被释放(出了大括号作用于)时,p变量仍然持有对象的所有权


 
   
 
   
2. __bridge_transfer 告诉ARC 一旦__bridge_transfer转换完成,ARC要负责释放该对象!相当于:
 
   
// p 变量原先持有对象的所有权
id obj = (id)p;
[obj retain];
[(id)p release];
//此后,ARC负责对obj对象所有权的管理
 
   
 
   
 
   



参考文章:
http://blog.csdn.net/weiwangchao_/article/details/7744972            Core Foundation 框架 (有详细的说明)
http://book.2cto.com/201305/23871.html            _objc_rootRetainCount 函数
http://www.cocoachina.com/applenews/devnews/2013/1126/7418.html   iOS内存管理策略和实践




  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值