objc源码
alloc的源码,需要去苹果的Source Browser下载最新的版本.
可以参考源码编译调试,直接在源码基础上跑起来,方便查看OC方法的底层实现步骤.
alloc
alloc
方法,可以说是最常见的类方法,在我们创建类对象时,是不可避免要使用到alloc,有人可能要质疑了,new
不可以创建类对象吗? 但其实new方法,还是会调用到alloc.
- 那么,alloc都做了什么?
有过iOS开发基础的都知道,alloc init方法,会为要创建的对象,开辟一段内存空间并初始化类对象.那我们来看下图.
alloc方法会去开辟空间,init方法没有对开辟的内存进行过修改
- 再深入探索以下:alloc是如何开辟空间的呢?
通过下载的objc源码,以及源码编译调试
中的搭建,我们可以直接点进去看到alloc的源码实现过程.
重点_class_createInstanceFromZone
其中关键的三个步骤:
-
-
size = cls->instanceSize(extraBytes);
1.1.
cache.fastInstanceSize(extraBytes)
1.2.
align16
// 其中`_flags`来自与当前类的标识,由_flags的不同,得出不同的结果,这里我们得到`size = 16`. size_t size = _flags & FAST_CACHE_ALLOC_MASK; // extra传进来的是0, FAST_CACHE_ALLOC_DELTA16=8 则align16(8) // align16方法 主要做的事情是16字节对齐,而现在iOS版本要求的就是16字节对齐 // 原因在于对象的isa指针占据8字节,如果按照8字节对齐方式,多个对象的isa连续排列,容易造成访问异常 // 所以最终return了 “16”, 即size = cls->instanceSize(extraBytes) = 16. return align16(size + extra - FAST_CACHE_ALLOC_DELTA16); 复制代码
-
-
obj = (id)calloc(1, size);
size个字节
的内存区域,返回obj是指向这块内存的 指针
.-
obj->initInstanceIsa(cls, hasCxxDtor);
这个方法会将开辟的内存关联到要创建的类.
总结:
alloc方法要做的事情为
- 由系统计算出开辟的内存空间大小
- 申请开辟得出的大小内存空间
- 将开辟的内存空间与要创建的类进行关联
init
init方法都做了什么?
由源码我们可以看到,init
方法只是返回了alloc得到的obj地址
,所以开头案例,p1、p2、p3指向的指针都是相同的.
new
new
的底层调用了callALloc
,是上边alloc
创建过程中的其中一个方法.
但是我们要在合适的地方使用new方法,因为它的弊端是,它没有办法调用重写自定义的init方法.
免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。
No more data