今天给各位分享深入解析iOS中的Tagged Pointer机制的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
关于Tagged Pointer
2013年9月,苹果推出iPhone5s。同时,iPhone5s搭载了首款采用64位架构的A7双核处理器。为了节省内存,提高执行效率,Apple提出了Tagged Pointer的概念。我们先来看一下原对象为什么会浪费内存。假设您要存储一个值为整数的NSNumber 对象。一般情况下,如果这个整数只是NSInteger的一个普通变量,那么它占用的内存和CPU位数有关。在32位CPU下占用4字节,在64位CPU下占用8字节。的。指针类型的大小通常与CPU位数有关。指针占用的内存在32位CPU下为4字节,在64位CPU下为8字节。因此,如果普通的iOS程序没有Tagged Pointer对象,从32位机器迁移到64位机器后,虽然逻辑没有改变,但NSNumber、NSDate等对象占用的内存会增加一倍。
直接引用大神的图片
为了存储和访问NSNumber 对象,我们需要在堆上为其分配内存,并维护其引用计数并管理其生命周期。这些给程序增加了额外的逻辑,造成运行效率的损失。
为了改善上面提到的内存占用和效率问题,Apple 提出了Tagged Pointer 对象。由于NSNumber、NSDate等变量的值占用的内存大小往往不需要8个字节,以整数为例,4个字节可以表示的有符号整数的数量可以达到20亿个以上。所以我们可以把一个对象的指针拆成两部分,一部分直接存储数据,另一部分作为特殊标记,表明这是一个不指向任何地址的特殊指针。
直接引用大师的图。所以,简单来说,可以理解为指针指向的内容直接放在了指针变量的内存地址中,因为在64位环境下,指针变量的大小达到了8位,也就是足以容纳一些较小的长度。内容。因此,采用标签指针方式来优化数据的存储方式。从引用计数可以看出,这是一个单例常量对象,无法释放。根据实际情况在运行时创建。
Tagged Pointer 示例
首先看NSNumber数值对象
muStr2=[NSMutableString stringWithString:@"1"];
for(int i=0; i20; i+=1){
NSNumber *number=@([muStr2 longLongValue]);
NSLog(@"%@, %p", [数字类别], 数字);
[muStr2appendString:@"1"];
}
//输出结果
__NSCF编号,0xb000000000000013
__NSCF编号,0xb0000000000000b3
__NSCF编号,0xb0000000000006f3
__NSCF编号,0xb000000000004573
__NSCF编号,0xb00000000002b673
__NSCF编号,0xb0000000001b2073
__NSCF编号,0xb0000000010f4473
__NSCF编号,0xb00000000a98ac73
__NSCF编号,0xb000000069f6bc73
__NSCF编号,0xb000000423a35c73
__NSCF编号,0xb000002964619c73
__NSCF编号,0xb000019debd01c73
__NSCF编号,0xb000102b36211c73
__NSCF编号,0xb000a1b01d4b1c73
__NSCF编号,0xb00650e124ef1c73
__NSCF编号,0xb03f28cb71571c73
__NSCF编号,0xb27797f26d671c73
__NSCF编号,0x60000003d540
__NSCF编号,0x61000003cb40
__NSCFNumber,0x61800003c760 值是1, 11, 111, 1111.这样递增。从输出指针的地址可以看出,最低4位总是3。这是用来标记long的(float为4,Int为2,double为5),“b”的最高4位表示NSNumber 类型;其余56 位用于存储值本身。当用于存储的值超过56位存储限制时,NSNumber将使用真正的64位内存地址来存储该值,然后使用指针指向该内存地址。 (如果值超过64位,就会崩溃)。
因为Tagged Pointed 不是一个真实的对象,所以它没有isa。但只要您避免在代码中直接访问对象的isa 变量,就可以了。具体来说,Tagged Pointer是如何访问类方法列表的呢?我们稍后会详细讨论。也许是根据最合适的类型标签,然后调用对应的类方法列表。
让我们看一下标记指针字符串
NSString *str=@"A";
NSString *str2=[[str mutableCopy] 复制];
NSLog(@"str:%p %@", str, str.class);
NSLog(@"str2:%p %@", str2, str2.class);
//输出结果
str:0x1068a2148 __NSCFConstantString
str2:0xa000000000000411 NSTaggedPointerStringString 的TaggedPointer 与Number 大致相同。最高位代表类型,最低位代表字符串长度。然后将字符串内容转换为ASCII码存储(上例A的ASCII码为65,转换为十六进制为41,而1的ASCII码为49,转换为十六进制为31)
NSMutableString *muStr2=[NSMutableString stringWithString:@"1"];
for(int i=0; i14; i+=1){
NSString *strFor=[[muStr2 mutableCopy] 复制];
NSLog(@"%@, %p", [strFor 类], strFor);
[muStr2appendString:@"1"];
}
//输出结果
NST标记指针字符串,0xa000000000000311
NST标记指针字符串,0xa000000000031312
NSTaggedPointerString,0xa000000003131313
NSTaggedPointerString,0xa000000313131314
NST标记指针字符串,0xa000031313131315
NSTagged指针字符串,0xa003131313131316
NST标记指针字符串,0xa313131313131317
NSTaggedPointerString,0xa0079e79e79e79e8
NSTaggedPointerString,0xa1e79e79e79e79e9
NSTaggedPointerString,0xa03def7bdef7bdea
NSTaggedPointerString,0xa7bdef7bdef7bdeb
__NSCF字符串,0x60000003e7c0
__NSCF字符串,0x61800003e5a0
__NSCFString,0x60800003e2c0 从上面的指针输出可以看出,最低位代表字符串的长度,剩下的56位也用来存储数组。这里需要注意的是,当字符串内存长度超过56位时,Tagged Pointer并没有立即使用指针进行重定向,而是使用算法以压缩的方式编码存储字符串的长度(我不太明白具体算法还没定)。当该算法压缩的数据长度超过56位时,就使用指针。 (点击查看具体算法编码,感谢评论区_黑苹果的解释)
【深入解析iOS中的Tagged Pointer机制】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
这篇文章终于写到了iOS开发里标记指针的概念!一直想了解一下。
有13位网友表示赞同!
标记指针听起来很酷啊,可以更好地管理内存吗?
有11位网友表示赞同!
希望这篇文章能详细讲解如何使用标记指针带来的优势。
有10位网友表示赞同!
对iOS开发者来说,学习标记指针能提升开发效率吗?
有18位网友表示赞同!
看标题感觉这篇文章内容比较技术性,需要仔细阅读理解。
有5位网友表示赞同!
MARK这个缩写是不是在计算机科学中常见啊?
有15位网友表示赞同!
终于有人整理出关于iOS标记指针的文章了!很期待学习新的知识。
有8位网友表示赞同!
学习完标记指针后,我可以写更安全的应用程序吗?
有16位网友表示赞同!
这篇文章会涵盖标记指针的应用场景吗?
有10位网友表示赞同!
在现代 iOS 开发中,标记指针的重要性如何?
有20位网友表示赞同!
之前在 Swift 中看到过类似的概念,这篇文章能让我更好地理解标记指针。
有15位网友表示赞同!
学习新的技术总是让人兴奋!我会仔细阅读这篇文章,学习iOS标记指针。
有6位网友表示赞同!
iOS开发一直是热门趋势,了解标记指针很有帮助。
有8位网友表示赞同!
这篇关于iOS标记指针的文章会不会比较难懂?
有12位网友表示赞同!
如果想学好标记指针,除了这篇文章还需要看哪些资源呢?
有5位网友表示赞同!
期待作者能用通俗易懂的方式讲解标记指针的概念!
有11位网友表示赞同!
我现在在学习iOS开发,标记指针这块的知识我还没接触过。
有16位网友表示赞同!
学习完标记指针之后,我能写出更快的应用程序吗?
有17位网友表示赞同!
这篇文章能帮我想办法解决一些内存问题吗?
有5位网友表示赞同!