OC 底层系统层知识内存

new 与 alloc 还有 free

2019-02-14  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读