前序
alloc使我们iOS开发者最常用的初始化对象的方法了,那么我们是否对alloc底层做了什么有了解呢?本文我们就来探索下alloc的底层实现。
alloc探究
代码探究
LGPerson *person1 = [LGPerson alloc];
LGPerson *person2 = [person1 init];
LGPerson *person3 = [person1 init];
NSLog(@"对象:\n%@\n%@\n%@\n",person1,person2,person3);
NSLog(@"对象地址:\n%p\n%p\n%p\n",person1,person2,person3);
NSLog(@"对象指针地址:\n%p\n%p\n%p\n",&person1,&person2,&person3);
打印结果:
2020-09-09 11:35:27.072554+0800 KCObjc[94267:2603966] 对象:
<LGPerson: 0x101320ec0>
<LGPerson: 0x101320ec0>
<LGPerson: 0x101320ec0>
2020-09-09 11:35:27.073109+0800 KCObjc[94267:2603966] 对象地址:
0x101320ec0
0x101320ec0
0x101320ec0
2020-09-09 11:35:27.073203+0800 KCObjc[94267:2603966] 对象指针地址:
0x7ffeefbff4d0
0x7ffeefbff4c0
0x7ffeefbff4c8
从上面我们发现,person1、person2、person3无论对象以及对象地址都是一样的,唯一不一样的是指向对象的指针地址不同。那么alloc内部到底实现了什么?我们通过源码来分析探究。
源码分析
-
alloc调用_objc_rootAlloc方法
-
callAlloc调用_objc_rootAllocWithZone
-
_objc_rootAllocWithZone调用_class_createInstanceFromZone
-
_class_createInstanceFromZone调用instanceSize方法获得开辟内存空间的大小
在instanceSize方法返回的大小是以16字节对齐,返回的是16的倍数
-
通过instanceSize方法获得开辟空间大小后通过calloc方法开辟空间
-
calloc开辟空间后通过clsinitInstanceIsa绑定对应的类,比如此处的LGPerson类
此处的cls就是LGPerson
alloc方法底层流程
init方法是干什么的
init方法是工厂方法,它没有实际的意义,主要是为了方便我们自定义初始化方法的,比如定义initWithXXX的方法
new与alloc init的关系
使用new初始化对象,会进入
从上图中我们点击callAlloc方法进入
方法,此时跟alloc没有什么区别了,因此我们可以总结new相当于alloc + init