oc指针和c语言区别,C 指针和OC 对象之间的转换方法
Core Foundation 框架
Core Foundation 框架 (CoreFoundation.framework) 是一组 C 语言接口, 简称 CF.
它们为 iOS 应用程序提供基本数据管理和服务功能.
如 Core Graphics、Core Text,并且我们可能需要将 CF 对象和OC 对象进行相互转化,ARC 下,编译器不会自动管理 CF 对象的内存,我们需要手动管理.
创建一个 CF 对象使用后, 需要使用 CFRelease 将其手动释放, 换句话说, Core Foundation 对象类型不在 ARC 管理范畴内.
如何将 CF 和 OC 对象有效的结合起来, 在 ARC 环境下, 提供了 桥接 的技术, 即 ARC 下 OC 对象和 Core Foundation 对象之间的桥梁.
ARC 桥接
ARC 下 C 指针与 OC 指针(对象)之间转换, 一般会用到下面的方法.
__bridge_retained )
__bridge_transfer )
__bridge )
也就是所谓的 桥接, 它是 Object-C 在 ARC 环境下开发出来的一种用作转换 C 指针跟 OC (类)指针的一种转换技术, 所以是 ARC 下的称谓, 在 MRC 下没有 桥接.
针对内存管理问题,ARC 可以管理 Objective-C 对象, 但不支持 Core Foundation 对象的管理,所以转换后要注意一个问题:谁来释放使用后的对象.
结合 ARC 和 内存管理, 下面分别介绍一下.
Core Foundation 对象必须使用 CFRetain 和 CFRelease 来进行内存管理.
当使用 Objective-C 和 Core Foundation 对象相互转换的时候,必须让编译器知道,到底由谁来负责释放对象,是否交给 ARC 处理, 只有正确的处理,才能避免内存泄漏和 double free 导致程序崩溃.
__bridge_retained )
__bridge_retained 等同于 CFBridgingRetain() .
将 Objective-C 对象转换为 Core Foundation 对象,把对象所有权桥接给 Core Foundation 对象,同时剥夺 ARC 的管理权,后续需要开发者使用 CFRelease 或者相关方法手动来释放 CF 对象.
示例:
void *cPointer;
NSObject *objc = [[NSObject alloc] init];
//将 OC 对象转换为 C 指针
cPointer = (__bridge_retained void*)objc;
//use cPointer ...
//需要释放资源
CFRelease(cPointer);
在 ARC 下, CFBridgingRetain 实现如下:
NS_INLINE CF_RETURNS_RETAINED CFTypeRef _Nullable CFBridgingRetain(id _Nullable X) {
return (__bridge_retained CFTypeRef)X;
}
关于 CFTypeRef, 如下:
typedef const CF_BRIDGED_TYPE(id) void * CFTypeRef;
所以 CFBridgingRetain 返回值是 const void * 类型的.
上面的示例可以改写为:
const void *cPointer;
const NSObject *objc = [[NSObject alloc] init];
cPointer = CFBridgingRetain(objc);
//use cPointer ...
CFRelease(cPointer);
__bridge_transfer )
__bridge_transfer 等同于 CFBridgingRelease() .
将非 OC 对象转换为 OC 对象,同时将对象的管理权交给 ARC,开发者无需手动管理内存.
示例:
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef strUUID = CFUUIDCreateString(kCFAllocatorDefault, uuid);
NSString *str = (__bridge_transfer NSString *)strUUID;
//无需释放 strUUID
//CFRelease(strUUID);
CFRelease(uuid);
CFBridgingRelease 实现如下:
NS_INLINE id _Nullable CFBridgingRelease(CFTypeRef CF_CONSUMED _Nullable X) {
return (__bridge_transfer id)X;
}
上面的示例可以改写为:
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef strUUID = CFUUIDCreateString(kCFAllocatorDefault, uuid);
NSString *str = CFBridgingRelease(strUUID);
//无需释放 strUUID
//CFRelease(strUUID);
CFRelease(uuid);
__bridge
__bridge 不改变对象所有权, 需要我们自己来管理内存, 它也是我们经常使用的方法, 从某种程度上来说, 它是上面两个方法的简化版本.
__bridge 可以将 OC 对象 与 C 指针相互转换, 示例:
//CFString -> OC 对象
CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "very", kCFStringEncodingUTF8);
NSString *nsString = (__bridge NSString *)cfString;
NSLog(@"CFString -> NSString: %@", nsString);
CFRelease(cfString);
如果将 CFRelease(cfString) 注释掉, Xcode 的静态检测器会告诉你有内存泄露的情况, 如图:
再来另外一个例子, 如下:
//OC 对象 -> CFString
NSString *nstr = @"itman";
CFStringRef cfStringRef = (__bridge CFStringRef)nstr;
NSLog(@"NSString -> CFString: %@", cfStringRef);
CFRelease(cfStringRef);
无论是使用 CFRelease(cfStringRef), 还是注释掉, 静态检测器都不会报错. 说明这种情况下, 当前的内存管理已经被 OC 对象管理.
野指针
运行下面的示例:
void *p;
{
NSObject *objc = [[NSObject alloc] init];
p = (__bridge void*)objc;
}
NSLog(@"mark: %@", (__bridge NSObject*)p);
会直接 crash, 如图:
当 objc 这个对象超出作用域范围,其内存就会被回收,接着在作用域范围外用 void *p 去访问 objc 的内存,就造成了野指针.
结合上面所说的, 我们可以让指针 p 对 objc 进行引用即 retain 操作, 修改如下:
void *p;
{
NSObject *objc = [[NSObject alloc] init];
//p = (__bridge void*)objc;
p = (__bridge_retained void*)objc;
}
NSLog(@"mark: %@", (__bridge NSObject*)p);
// 一定要释放
CFRelease(p);
可以正常的运行. 还可以修改为另一种方式:
void *p;
{
NSObject *objc = [[NSObject alloc] init];
//p = (__bridge void*)objc;
//p = (__bridge_retained void*)objc;
p = (void *)CFBridgingRetain(objc);
}
NSLog(@"mark: %@", (__bridge NSObject*)p);
// 一定要释放
CFRelease(p);
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
oc指针和c语言区别,C 指针和OC 对象之间的转换方法相关推荐
- 数组c语言与指针,浅析C语言数组与指针
摘 要:数组和指针是C语言的两个最重要的概念,它们若结合起来使用,非常灵活,初学者往往感到无所适从,笔者根据多年的经验,利用典型实例和图表对指向一维数组的指针的定义和数组元素的引用.指针与自增自减运算 ...
- c语言程序设计指针教学,C语言程序设计中指针教学要点分析
C语言程序设计中指针教学要点分析 徐 兵 ( 广东海洋大学信息学院, 广东 湛江 524088) 1 指针知识单元构成 1.1 指针定义 在计算机内存中, 每一个存储单元(通常为 1 字节 )都有一个 ...
- c语言数组数据用指针查找,c语言数组与指针_指针篇_2011.ppt
c语言数组与指针_指针篇_2011 指 针 6.2 指针的概念6.3 指针与数组6.4 字符串的指针6.5 指针数组和指向指针的指针;6.2.1 地址与指针的概念 ;指针的概念;内存地址;2.数组与地 ...
- C语言 指针 规范,C语言学习知识指针习题集附规范标准答案.doc
C语言学习知识指针习题集附规范标准答案.doc /*一.选择题1. 变量的指针,其含义是指该变量的_________. a值 b地址 c名 d一个标志2若有语句int *point,a4;和point ...
- c语言+结构体指针初始化,c语言结构体指针初始化===
c语言结构体指针初始化 今天来讨论一下C中的内存管理. 记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面 我说所有指针使用前都必须初始化,结构体中的成员指针也是一样 有人反驳说,不是吧,以 ...
- c语言野指针应用,C语言中野指针的深入解析
C语言中野指针的深入解析 C语言中野指针这一块是C语言的难点,下面小编为大家带来了C语言中野指针的深入解析,欢迎大家阅读! "野指针"的成因主要有两种: (1)指针变量没有被初始化 ...
- c语言结构体指针详解,结构体指针,C语言结构体指针详解
结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过"结构体变量名.成员名"的方式引用结构体变量中的成员,除了这种方法之外还可以使用 ...
- c语言中结构体的指针初始化,c语言结构体指针初始化
今天终于看完了C语言深度剖析这本书,对C语言有了进一步的了解与感悟,突然发觉原来自己学C语言的时候学得是那样的迷糊,缺少深入的思考,在重新看书的时候发觉C语言基本教材虽然经典,但是缺乏独到性,老师在讲 ...
- 指针冒泡排序c语言代码,用指针编写冒泡排序方法
满意答案 ha141988 2013.05.26 采纳率:44% 等级:13 已帮助:10095人 需要修改三个地方:(确保程序正常运行) 1.scanf("%d",*ptr ...
最新文章
- 聊聊flink的InternalTimeServiceManager
- 处方上电脑 北大口腔医嘱一清二楚
- AWS DataPipline 的一次尝试。
- C语言定义一个头节点,一个关于C语言链表头结点的问题
- 为什么我建议你现在学Vue3?
- apicloud手机查看效果
- Windows 下使用 SecureCRT 将本地文件上传至远程的 Linux 服务器,中文乱码怎么办?
- 1014.QxORM移植
- Bailian2767 简单密码(POJ NOI0107-10)【密码】
- Ubuntu中锐捷客户端的配置与使用
- 实现Springboot整合UReport2
- 电脑版微信防撤回大全
- python 搭建服务器
- Microsoft SQL Server 2000的版本区别及选择
- mysql中日期相减_解放双手!用这3个日期函数解决入职、工龄等天数的计算
- pandas制作图表
- 华为设备MPLS LDP配置命令
- Zabbix 3.4配置监控项及监控Linux、Windows客户端
- 【Unity开发总结】C# 闭包陷阱
- Linux下EPICS的安装与配置——Phoebus配置与PV连接