内存布局
栈区
:函数,方法
堆区
:通过alloc分配的对象,block copy
.bss
:未初始化的全局变量,静态变量
数据段
:初始化的全局变量,静态变量
text
:程序代码,加载到内存中
TaggedPointer
小对象类型。通常存储NSString ,NSNumber,NSDate等等这些类型。
先看一个例子:(xcode模拟器环境)
我们可以清楚地看到此时的self.nameStr
是taggedpointer类型。注意看右边的lldb调试,下面放大分析:
0b1010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0010 0110 0001 0010
1、最前面的0b1
代表这个是个taggedpointer类型。
2、紧跟着的010
代表这个是一个NSString类型。
3、后面的0110 0010
代表字符b。
4、再接着的0110 0001
代表字符a。
5、最后的0010
代表字符串的长度是2。
附录:
1、NSString是2,NSNumber是3,NSIndexPath 是4,NSDate是6.更多类型,见下图
2、二进制代表字符请查询ASCII表。
可以看到此NSString被优化了,他的指针和值是在一块的。合适存储一些小数据类型。从二进制数据中也可以看出,前后之间的字段可以存储值,一旦超过此字段。NSString将不被优化。具体见下表:
再来一个例子看看实际情况:(xcode模拟器环境)
增加字符串长度,此时变成NSCFString了。
引用计数处理:
打开源码:objc_setProperty()
->reallySetProperty()
,对新值的retain
,对旧址的release
查看objc_retain
和objc_release
对TaggedPointer
的处理,直接返回了,不做处理。
attribute__((aligned(16), flatten, noinline))
id
objc_retain(id obj)
{
if (obj->isTaggedPointerOrNil()) return obj;
return obj->retain();
}
__attribute__((aligned(16), flatten, noinline))
void
objc_release(id obj)
{
if (obj->isTaggedPointerOrNil()) return;
return obj->release();
}
总结:
1、taggedpointer专门用来存储小的对象类型,例如NSSTring,NSdata等。
2、taggedpointer指针的值不再是地址了,而是真正的值。所以,实际上他不再是一个对象了,他只是一个披着对象外衣的普通变量而已。所以,他的内存并不在堆中,也不需要malloc和free。
3、在内存读取上有着3倍的效率,创建时比以前快106倍。