先看一段测试代码
打印一下内存地址和所属类
__NSCFconstantString是常量字符串,那么它肯定是储存在常量区。
__NSCFString表示为oc对象,通过地址可以看出来这个字符串储存在堆中。
NSTaggedPointerString类是储存在栈区中的。Tagged Pointer技术
文章的大致意思是这样的:Tagged Pointer是一个能够提升性能、节省内存的有趣的技术,NSString就采用了这种技术。比如一个64位内存0xa000000000000011其中a的2进制为1010,第一个1表示该指针为Tagged Pointer,后边的三位则表示一个类表的索引,该索引是用来查找所属类是采用Tagged Pointer的哪个类,剩下的60位留给类来使用。Tagged Pointer的值不再是地址,它本身就是一个值,只是伪装成了地址而已。而且Tagged Pointer也不是一个真正的对象,它没有isa指针,所以不能直接访问Tagged Pointer的isa成员。
str_4中mutableCopy和copy是必要的,字符串常量从不存储为Tagged Pointer,因为字符串常量必须在不同操作系统下保持二进制兼容,而Tagged Pointer的内部细节是没有保证的。其能使用的前提是Tagged Pointer在运行时总是有Apple的代码生成,如果编译器把他们嵌入到二进制里,那么前提就被打破了(字符串常量就是这样)。因此需要copy常量字符串来获取Tagged Pointer。mutableCopy是必要的,原文说NSString太聪明(说的好人性化),而且也知道一个不可变字符串的副本是一个毫无意义的操作,所以他会返回原字符串当做copy。字符串常量是不可变的,所以[str_4 copy]结果只是str_4。一个可变的副本强迫他产生真正的副本,这样一个可变量副本的不可变副本足以让系统产生一个采用Tagged Pointer的字符串。
str_5和str_6样式基本是一样的但是他们的在内存中的位置却是不一样的,str_6是储存在堆区的。NSTaggedPointerString类的存储有三种编码方式,分别是ASCII码,六位编码,五位编码。ASCII码字符串数目在0~7之间,六位编码8~9,五位编码10~11(这个也不是一成不变的,可能会随apple的更新而变)。str_6的字符比较多所以就被存入堆中了。
网友评论