• 1

  • 558

alloc方法底层探索

云哥

关注云计算

1星期前

objc源码

alloc的源码,需要去苹果的Source Browser下载最新的版本.

可以参考源码编译调试,直接在源码基础上跑起来,方便查看OC方法的底层实现步骤.

alloc

alloc方法,可以说是最常见的类方法,在我们创建类对象时,是不可避免要使用到alloc,有人可能要质疑了,new不可以创建类对象吗? 但其实new方法,还是会调用到alloc.

  • 那么,alloc都做了什么?

有过iOS开发基础的都知道,alloc init方法,会为要创建的对象,开辟一段内存空间并初始化类对象.那我们来看下图.

由上图我们看到,p1、p2、p3所指向的内存空间都是相同的,也就说明,只有 alloc方法会去开辟空间,init方法没有对开辟的内存进行过修改
  • 再深入探索以下:alloc是如何开辟空间的呢?

通过下载的objc源码,以及源码编译调试中的搭建,我们可以直接点进去看到alloc的源码实现过程.

重点_class_createInstanceFromZone

其中关键的三个步骤:

    1. 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);
      
      复制代码

    1. obj = (id)calloc(1, size);
这个方法,会开辟 size个字节的内存区域,返回obj是指向这块内存的 指针.

    1. obj->initInstanceIsa(cls, hasCxxDtor);
      这个方法会将开辟的内存关联到要创建的类.

总结:

alloc方法要做的事情为

  1. 由系统计算出开辟的内存空间大小
  2. 申请开辟得出的大小内存空间
  3. 将开辟的内存空间与要创建的类进行关联

init

init方法都做了什么?

由源码我们可以看到,init方法只是返回了alloc得到的obj地址,所以开头案例,p1、p2、p3指向的指针都是相同的.

new

new的底层调用了callALloc,是上边alloc创建过程中的其中一个方法.

但是我们要在合适的地方使用new方法,因为它的弊端是,它没有办法调用重写自定义的init方法.

免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

云计算

558

相关文章推荐

未登录头像

暂无评论