美文网首页iOS底层原理
alloc在底层干了什么?init又干了什么?new又干了什么?

alloc在底层干了什么?init又干了什么?new又干了什么?

作者: 何必太轻浮 | 来源:发表于2020-09-06 21:19 被阅读0次

我们最常用的创建对象方法一般是

MCPerson *objc1 = [[MCPerson alloc]init];
//or
MCPerson *objc2 = [MCPerson new];

这两个创建方法有什么区别呢,我们先针对第一个alloc,init创建对象的流程进行分析

  • alloc到底干了什么?


    pic1

如图我们发现,对象在alloc的时候已经被创建出来了,于是我们先重点看看alloc主要干了什么。

于是,在上图第15行打下断点,重新运行


pic2

断点断住这里(objc_alloc)


pic3

往下走,到了定义objc_alloc的地方,调用了callAlloc方法


pic4

继续往下走,到了callAlloc定义的地方,这个地方会调用两次,第一次走objc_msgSend方法,第二次走_objc_rootAllocWithZone方法


pic5

继续往下走,到了class_createInstanceFromZone方法,这就是大致alloc方法的调用流程了


pic5

class_createInstanceFromZone 这个方法比较重要,里面包含 计算对象大小,申请内存(16字节对齐),绑定类这几个操作

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
                              int construct_flags = OBJECT_CONSTRUCT_NONE,
                              bool cxxConstruct = true,
                              size_t *outAllocatedSize = nil)
{
    ASSERT(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();
    size_t size;
    // 1:要开辟多少内存
    size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (zone) {
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        // 2;怎么去申请内存
        obj = (id)calloc(1, size);
    }
    if (slowpath(!obj)) {
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }

    // 3: 绑定类
    if (!zone && fast) {
        obj->initInstanceIsa(cls, hasCxxDtor);
    } else {
        // Use raw pointer isa on the assumption that they might be
        // doing something weird with the zone or RR.
        obj->initIsa(cls);
    }

    if (fastpath(!hasCxxCtor)) {
        return obj;
    }

    construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
    return object_cxxConstructFromClass(obj, cls, construct_flags);
}

alloc流程绘制成流程图


pic6

简单来说,alloc方法调用完后,对象已经创建了

  • init方法干了什么呢?
    点击init方法,直接查看源码,发现啥都没做,只是返回了init方法,所以init只是一个简单的工厂设计模式,主要是方便我们重写这个方法


    pic7
  • new方法干了什么呢?
    new方法进入源码,发现,其实new方法就是在底层同时调用了alloc和init方法


    pic8

在这里思考一个问题,在底层调用init方法,是调用NSObject的init方法还是子类重写的?

  • 我在子类重写了init方法,使用new初始化对象
pic9 pic9 pic10

发现,其实new方法也是会遵循方法查找原则的,so,alloc、init、new方法简单的分析就到这里了,有兴趣的小伙伴可以关注我哦,我会继续更新的哦。

objc源码下载地址:
https://opensource.apple.com/tarballs/
https://opensource.apple.com

相关文章

  • alloc在底层干了什么?init又干了什么?new又干了什么?

    我们最常用的创建对象方法一般是 这两个创建方法有什么区别呢,我们先针对第一个alloc,init创建对象的流程进行...

  • alloc与init探索

    知识点概要 引入alloc干了什么?为什么要有init?为什么要有new?直接使用有何缺陷?[NSObject a...

  • 系统底层源码分析(11)——alloc、init、new

    我们知道alloc、init、new就是开辟内存空间初始化对象,今天就来探讨一下它们分别在底层干了什么。 一. a...

  • [iOS] alloc&init源码学习记录

    在开发过程中,有时会有一个疑问:alloc&init究竟做了什么? alloc 是分配内存,init 具体干了点啥...

  • oc对象探索 alloc&init

    初步探索 alloc 和 init 要知道alloc 和 init 都干了什么事情 我们从内存地址和指针地址来分析...

  • new都干了些什么

    用Java写代码的时候,感觉用的最多的便是new了吧,这几天在恶补Java基础知识的时候突然想到,我们在new一个...

  • 没什么大不了~

    你不干,她不干,大家都靠着,我干了,又怎样,放宽心,不要紧,干了就干了,没什么大不了。

  • 记流水账

    今天微信上收到儿子发来的日记,四个字即可概括――记流水账(早上几点起床,干了什么事情,又干了什么,最后干了什...

  • 详细探究alloc到底干了什么?

    1、怎么去探究alloc? 我们在xcode中按住command键点进去就进入了一下页面 到这个页面之后,就再也无...

  • vue源码分析.md

    New Vue发生了什么 Vue定义为一个函数,new的过程相当于实例化Vue。 在init方法中主要干了这几件事...

网友评论

    本文标题:alloc在底层干了什么?init又干了什么?new又干了什么?

    本文链接:https://www.haomeiwen.com/subject/sfkfektx.html