Objc-原来你是这样的alloc

image.png

alloc内部到底做了什么?一般都知道开辟内存创建实例。
先看源码:经过查看多个文章发现objc的alloc方法一直也在优化。
先贴几个我查找的文章:
http://www.cocoachina.com/articles/29200
https://blog.csdn.net/u014600626/article/details/86714085
当前文章介绍版本是objc4-787.1版本(2020年12月01日最新)
先贴一个我根据源码花的流程图(如有不对欢迎指正)
alloc流程图.jpg

相关源码

alloc实现

+ (id)alloc {
    return _objc_rootAlloc(self);
}
_objc_rootAlloc 🔽
id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
callAlloc🔽
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && !cls)) return nil;// cls 为空返回
    if (fastpath(!cls->ISA()->hasCustomAWZ())) { // 如果 cls 没有实现自定义 allocWithZone 方法
        return _objc_rootAllocWithZone(cls, nil); // 调用 _objc_rootAllocWithZone
    }
#endif

    // No shortcuts available.
    if (allocWithZone) { // 如果 allocWithZone 为 true,调用 allocWithZone 创建对象
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));// 否则调用 alloc 方法创建对象
}

查看上面文章这个方法做了优化,开辟内存的代码移到了_class_createInstanceFromZone方法

_objc_rootAllocWithZone🔽
id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
    // allocWithZone under __OBJC2__ ignores the zone parameter
    return _class_createInstanceFromZone(cls, 0, nil,
                                         OBJECT_CONSTRUCT_CALL_BADALLOC);
}
_class_createInstanceFromZone 开辟内存创建实例🔽
static ALWAYS_INLINE id
_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());

    // 同时读取类的所有信息以提高性能
    bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();
    size_t size;
    // 计算需要的空间大小
    size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (zone) {// 申请内存
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        obj = (id)calloc(1, size);
    }
    if (slowpath(!obj)) {// 返回错误信息
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }
    // 创建isa指针
    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);
}

看之前的文章,在callAlloc中就申请内存空间创建isa,返回对象。到这个版本苹果将申请内存和创建isa的代码抽离,还做了好多的优化,所以说苹果的代码在不断优化中。不是有了Swift就不要OC了。

原来你是这样的alloc(如有疑问欢迎评论一起讨论)

image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容