new 与 alloc 还有 free

作者: 介和 | 来源:发表于2019-02-14 14:54 被阅读0次

       className* object = [className new];

      or

        className* object = [[className alloc] init];

    背景说明,new是较为老式的写法,后来发现只有一个new不好使,才引入了alloc和init这种写法,保留new一是向后兼容,二是很多时候是一种更简单的写法。其实是一样的,new在内部调用的alloc和init.

    源代码:

    + new

    {

    id newObject = (*_alloc)((Class)self, 0);

    Class metaClass = self->isa;

    if (class_getVersion(metaClass) > 1)

            return [newObject init];

    else

        return newObject;

    }

    + alloc

    {

    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); 

    }

    - init

    {

        return self;

    }

    [className new]基本等同于[[className alloc] init]. 区别只在于alloc分配内存的时候使用了zone,这个zone是个什么东东呢?它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度.

    什么要把alloc 和init 分开?

    1. 可以使用多种init方法

    2. 显示调用总比隐式调用要好”

    如果确实不需要用其他的init函数,比如initWithString, 只是使用 [Nsobject alloc] init] ,那用new的方法更加方便

     * new doesn't support custom initializers (like initWithString)

     * alloc-init is more explicit than new

    深挖:  (*_zoneAlloc)  与  (*_alloc)

    id (*_zoneAlloc)(Class, size_t, void *) = _class_createInstanceFromZone;

    PRIVATE_EXTERN id

    _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)

    {

        id obj;

        size_t size;

        // Can't create something for nothing

        if (!cls) return nil;

        // Allocate and initialize

        size = _class_getInstanceSize(cls) + extraBytes;

        // CF requires all objects be at least 16 bytes.

        if (size < 16) size = 16;

    #if SUPPORT_GC

        if (UseGC) {

            obj = (id)auto_zone_allocate_object(gc_zone, size,

                                                AUTO_OBJECT_SCANNED, 0, 1);

        } else

    #endif

        if (zone) {

            obj = (id)malloc_zone_calloc (zone, 1, size);

        } else {

            obj = (id)calloc(1, size);

        }

        if (!obj) return nil;

        obj->isa = cls;

        if (_class_hasCxxStructors(cls)) {

            obj = _objc_constructOrFree(cls, obj);

        }

        return obj;

    }

    上面那段代码的作用是:

    1、得到这个类占用多少空间,最小占16 bytes

    2、然后就给这个实例分配多少空间, 如果失败的话就返回nil

    3、把这个实例的isa设置成这个类对象

    4、如果cls的info设置了get属性就用cls这个类在obj这个空间去构造一个实例,跟进去是

    id (*_alloc)(Class, size_t) = _class_createInstance;

    static id _class_createInstance(Class cls, size_t extraBytes)

    {

        return _class_createInstanceFromZone (cls, extraBytes, NULL);

    }

    free

    - free

    {

        return (*_dealloc)(self);

    }

    + free

    {

        return nil;

    }

    _object_dispose

    static id  _object_dispose(id anObject)

    {

        if (anObject==nil) return nil;

        objc_destructInstance(anObject);

    #if SUPPORT_GC

        if (UseGC) {

            auto_zone_retain(gc_zone, anObject); // gc free expects rc==1

        } else

    #endif

        {

            // only clobber isa for non-gc

            anObject->isa = _objc_getFreedObjectClass ();

        }

        free(anObject);

        return nil;

    }

    objc_destructInstance

    void *objc_destructInstance(id obj)

    {

        if (obj) {

            Class isa = _object_getClass(obj);

            if (_class_hasCxxStructors(isa)) {

                   object_cxxDestruct(obj);

            }

            if (_class_instancesHaveAssociatedObjects(isa)) {

                _object_remove_assocations(obj);

            }

            if (!UseGC) objc_clear_deallocating(obj);

        }

        return obj;

    }

    执行一个叫object_cxxDestruct的东西干了点什么事(沿着继承链逐层向上搜寻SEL_cxx_destruct这个selector, 找到函数实现(void (*)(id)(函数指针)并执行)

    执行_object_remove_assocations去除和这个对象关联的对象

    执行objc_clear_deallocating,清空引用计数表并清除弱引用表,将所有weak引用指nil

    ---------------------

    参考:https://blog.csdn.net/uxyheaven/article/details/38120335

    https://blog.csdn.net/lixin8201/article/details/50407955

    https://blog.csdn.net/u013375242/article/details/49512183

    相关文章

      网友评论

        本文标题:new 与 alloc 还有 free

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