如果你看过我前面两篇objc函数枢纽msgSend你印象中的NSString是这样吗,相信已经多次看过它的身影了,到底它是何物何作用,我今日就来揭开谜团。
我之所为称呼它为伪指针,是因为它像幽灵一样,没有肉身(实例)但却在能像objc对象实例那样表现出各种行为。你能猜出下面代码运行的结果吗?

// non-arc
id unknown = (id)0x12345678;
NSLog(@"%@", unknown);
unknown = (id)0xa000000000032312;
NSLog(@"%@", unknown);
NSString* s12 = [NSString stringWithUTF8String:""];
NSLog(@"%@", s12);
[s12 isEqualToString:unknown];
NSLog(@"%d", *(int64_t*)&s12 == *(int64_t*)&unknown);

如果我随便编写一个地址0x12345678,然后用这个地址进行objc调用,[(id)0x12345678 retain]。相信大家第一反应是我正在对一个不明白的地址访问,指向这个地址的指针大家叫它野指针,我正在向一个“野指针”操作。

如果我又随便编写一个地址像这们0xa000000000032312,并对这个地址进行objc调用[(id)0xa000000000032312 retain]。相信大家的反应是和上面举例的情况一样,尽管当中有人看过我们前面的文章知道这是一个TaggedPointer,但是我还是在对一个不可信的地址进行操作,当访问0xa000000000032312内存地址的内容时将要出错。

但结果却是,0xa000000000032312地址的操作合法,并且用NSLog(@"%@", (id)0xa000000000032312)还打印出12。

大家都熟悉实例的构建过程,如[[NSString alloc] init]和[NSString string]。都必须为对像实例分配空间然后初始化。然而地址0xa000000000032312只是我随便编造的,完全没有在那个地址上分配过空间。
我再来调用[NSString stringWithUTF8String:"12"],返回了一个类型是NSTaggedPointerString实例的指针。指向的地址正是0xa000000000032312。直到这时0xa000000000032312的实例才被构建,然而对这个地址一访问还是一个非法地址。

所以TaggedPointer只是一个伪指针,它的真相就在这个指针指向的地址的数值本身。
0xa000000000032312这个数值就像一个被压缩的对像实例一样,最高4位是isa的线索,参考前面介绍反汇编msgSend文章,最低8位是info信息,中间第9位起的48位是对像的content。用这副幽灵镜来再看0xa000000000032312,什么都一清二楚了,{isa=0xa,coutent='\x31\x32',len=2}。这是NSString中一种名为EightBitsEncoding的情况。

为什么要有TaggedPointer,就让我们来看一下性能。
用profile分别查看循环100M次的[@"ab" stringAppendByString:@"c"]和[NSString stringWithUTF8String:"abc"];
上一篇的例子可以找到[@"ab" stringAppendByString:@"c"]返回__NSCFString, [NSString stringWithUTF8String:"abc"]返回NSTaggedPointerString。
究竟它们之间有什么样的性能差别呢?由于我的机器性能有限,profile时几近运行不过来,所以没有图可截贴出,只能陈述一下情况。先是[@"ab" stringAppendByString:@"c"]返回__NSCFString的情况,CFString不断地在缓慢分配,待到分配了1M个时,内存占用了50M,机器在profile运行中惨不忍睹,我果断中止了。另一方面[NSString stringWithUTF8String:"abc"]返回NSTaggedPointerString的profile中,CFString数量没有增长,内存自然也没有消耗。好我将循环次数减少至1M次,不做profile,直接运行对比,NSTaggedPointerString的情况明显要快出几倍,因为根本没有构建过实例(,用于返回的实例,中间里面的过程一样还有其它临时实例的)。

除了NSTaggedPointerString还有其它的TaggedPointer,你知道0xb0000000000000c2是什么吗,赶紧试一试。

最后多谢大家再次观看。

objc里的伪指针TaggedPointer的更多相关文章

  1. 【转】JavaScript里的this指针

    用自然语言的角度理解JavaScript中的this关键字 <script type="text/javascript"> function ftn03(){ var ...

  2. Keil C51里关于堆栈指针的处理

    Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好.这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址 ...

  3. Linux 内核里的“智能指针”【转】

    转自:http://blog.jobbole.com/88279/ 众所周知,C/C++语言本身并不支持垃圾回收机制,虽然语言本身具有极高的灵活性,但是当遇到大型的项目时,繁琐的内存管理往往让人痛苦异 ...

  4. (转)C++11里的智能指针

    1. std::auto_ptr有些违背c++编程思想. 已经被"不建议使用了".2. 下文转自:http://blog.csdn.net/lanergaming/article/ ...

  5. objective-c里的方法指针IMP的用法

    SGPopSelectView.h @interface SGPopSelectView : UIView @property (nonatomic, assign) SEL selector; @p ...

  6. 关于引用(python中的伪指针)的理解

    # 总结:个人理解,引用不可变的的变量时,随着改变会指向新的地址 # 引用可变的变量时,位置不会随着变量改变而改变 a = 1 b = a print(b) a = 2 # 指向了新的内存地址 pri ...

  7. Objc中2维指针作为输出参数时由ARC及@autoreleasepool引发的血案

    先看下面一个例子 #import <UIKit/UIKit.h> #import "AppDelegate.h" @interface Something : NSOb ...

  8. 反汇编看c++引用

    继续反汇编系列,本次使用vc2008在x86体系下分析c++中的引用. 定义一个引用类型和将一个变量转换成引用类型一样吗? 引用比指针安全,真的是这样吗,对引用不理解的话比指针还危险. 为什么要用常量 ...

  9. 函数指针的返回值是指针数组,数组里放的是int;函数指针的返回值是指针数组,数组里放的是int指针

    函数指针的返回值是指针数组,数组里放的是int 函数指针的返回值是指针数组,数组里放的是int指针 #include <stdio.h> #include <stdlib.h> ...

随机推荐

  1. Opentracing + Uber Jaeger 全链路灰度调用链,Nepxion Discovery

    当网关和服务在实施全链路分布式灰度发布和路由时候,我们需要一款追踪系统来监控网关和服务走的是哪个灰度组,哪个灰度版本,哪个灰度区域,甚至监控从Http Header头部全程传递的灰度规则和路由策略.这 ...

  2. 2019.10.29 CSP%您赛第四场t2

    我太菜了我竟然不会分层图最短路 ____________________________________________________________________________________ ...

  3. Kafka权威指南阅读笔记(第八章)

    跨集群数据镜像 使用场景: 区域集群和中心集群 这种场景下,每个区域的应用程序只访问相应的区域内的集群.而有些情况下,需要将各个集群的信息汇总到中心集群,就可以用中心集群分析业务数据了. 冗余 一个K ...

  4. R语言之脸谱图

    脸谱图和星图类似,但它却比星图可以表示更多的数据维度.用脸谱来分析多维度数据,即将P个维度的数据用人脸部位的形状或大小来表征.脸谱图在平面上能够形象的表示多维度数据并给人以直观的印象,可帮助使用者形象 ...

  5. UIScrollView的contentView 助于理解

  6. python3openpyxl库的简单使用

    python3操作表格有很多库,现在主要给大家介绍一下我比较喜欢用的openpyxl库,安装直接pip安装,对pip安装有疑问可以参考我有关于pip使用的文章. wb=Workbook()#新建表格 ...

  7. 详解PHP中的三大经典模式

    单例模式 单例模式的含义: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 单例模式 ...

  8. UiPath之数据透视表

    今天给各位小伙伴们讲讲如何使用UiPath来创建数据透视表,相信大家在Execl中经常会使用. ---小U的QQ群(714733686):小U的订阅号[UiPath8888]--- 在UiPath里面 ...

  9. 机器学习环境搭建安装TensorFlow1.13.1+Anaconda3.5.3+Python3.7.1+Win10

    安装Python3.7.1 此处不再赘述安装过程,作为记录 安装Anaconda3.5.3 Anaconda3-5.3.0-Windows-x86_64.exe 方案1. 可以直接从官网https:/ ...

  10. Python实现王者荣耀小助手(一)

    简单来说网络爬虫,是指抓取万维网信息的程序或者脚本,Python在网络爬虫有很大优势,今天我们用Python实现获取王者荣耀相关数据,做一个小助手: 前期准备,环境搭建: Python2.7 sys模 ...