追踪
在探究alloc的工作流程时,会追踪到class_createInstance方法中
但是class_createInstance直接字面意思就是创建“实例”,创建谁的实例啊,就是是传入的 cls,也就是我们的Person,至于 extraBytes 为啥就直接传了个0,还不知道。
_class_createInstanceFromZone
继续追踪_class_createInstanceFromZone:
instanceSize获取实例对象的size
别的先别管,直接断点来到instanceSize ,创建一个对象,我们先得给他个大小Size吧,好,直接点击去追踪
alignedInstanceSize —->word_align(unalignedInstanceSize())—->data()->ro->instanceSize.至于data()->ro->instanceSize意思就是拿到cls所有的属性所占空间大小,但是Person类没有添加属性,只有一个隐藏的isa,这家伙占8个字节,通过lldb可以看到输出为8,好,传入word_align(8),点进去看:
WORD_MASK根据架构不同具体数值也不同,在这里当成7
#ifdef __LP64__# define WORD_SHIFT 3UL# define WORD_MASK 7UL# define WORD_BITS 64#else# define WORD_SHIFT 2UL# define WORD_MASK 3UL# define WORD_BITS 32#endif
所以 (x + WORD_MASK) & ~WORD_MASK 的作用就是把(8+7)& ~7转为二进制
15 0000 11117 0000 0111~7 1111 1000然后进行与操作:15&~70000 1111&1111 1000=8 0000 1000
计算一遍得出word_align()返回8到alignedInstanceSize(),这一步做的操作其实就是将参数x进行8的规整,给你加上个7,看你能不能进级的8的上一层倍数。
CPU在给对象分配内存空间的时候,也不能你要多少就给多少,要1给1,要3给3的,这样虽然省空间,但是读起来好麻烦,一次读多少也不知道,读少了没读完,读多了,读到别人家去了,多尴尬。所以这里根据不同的架构有不同字节的对齐方式,高大上的名字叫“字节对齐”,我们接触的应该就是64位8字节对齐。这样,CPU每次读8个字节,可以称之为以空间换取时间。但是如果仅仅占用1字节的空间,分配给8字节是不是有点浪费,当然不能,CPU还会做一些内存优化,内存对齐了解一下。
size_t size = alignedInstanceSize() + extraBytes;// CF requires all objects be at least 16 bytes.if (size < 16) size = 16;return size;
CF requires all objects be at least 16 bytes.CF要求对象最少16字节。
calloc申请内存空间
知道了size,那就直接开干,调用calloc,向内存申请size大小的空间,并返回一个obj的对象。
initInstanceIsa初始化isa
创建实例,现在实例有了空间了,那么这个空间和谁相关联呢,这就是isa的一个小作用。将内存空间和类进行关联。
回到_class_createInstanceFromZone方法中往下走,找到obj->initInstanceIsa(cls, hasCxxDtor)
obj是_class_createInstanceFromZone返回值,也就是它就是我们创建的对象,具体这个对象是什么类型的还不知道,现在它的类型还是id,也就是和Person还没有关联起来。好,调试点击:
看到没有,在执行完initInstanceIsa方法之后,我们的obj已经是Person类的一个对象,也就是obj已经和我们的Person关联起来了。
