熟悉又陌生的alloc、init、new

有些東西你看著懂了,面試的時候傻眼了,緊張、后悔各種情緒撲面而來,熟悉又陌生帶來的最終的結(jié)果是GG。

思考壹:大家想過我們創(chuàng)建對象的時候?yàn)楹蜗纫猘lloc,然后又要init呢?還是說在我們看來這就是個定律,不用管它的證明,只管用即可?

熟悉的身影:

MyJob *job = [MyJob alloc] init ] ;

熟悉又陌生的身影:

MyJob * job = [MyJob alloc] ;
MyJob * jobOne = [job init] ;
MyJob * jobTwo = [job init] ;

猜猜job、jobOne、jobTwo三個對象指針指向的地址是一樣的嗎?

1.分析一下[MyJob alloc]在底層都發(fā)生了什么?

alloc:根據(jù)傳入的class對象,返回一個該類的實(shí)例對象,并在內(nèi)存中申請分配空間,根據(jù)對象的實(shí)例變量,屬性的類型使用字節(jié)對齊的算法來計算所需的內(nèi)存的大小。

alloc流程
1.1、一個對象需要分配多大的內(nèi)存呢?又是如何計算的呢?怎么去查看分配內(nèi)存的大小呢?
@interface MyJob : NSObject
{
    NSString *name;
    int       money;
}
@end

兩種方法查看一個對象分配內(nèi)存的大?。?br> 第一種:驗(yàn)證方法還是instrument


instrument顯示的內(nèi)存大小

第二種:runtime中class_xxx方法

/**
 * Returns the size of instances of a class.
 *
 * @param cls A class object.
 *
 * @return The size in bytes of instances of the class \e cls, or \c 0 if \e cls is \c Nil.
 */
OBJC_EXPORT size_t class_getInstanceSize(Class cls)
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

runtime中對instanceSize做了判斷(CF requires all objects be at least 16 bytes):

size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }
類型大小圖

2、init又做了什么呢?為何我們初始化對象的時候總是不由自主的在后面加上init呢?

- (id)init {
   return _objc_rootInit(self);
}
id
_objc_rootInit(id obj)
{
   // In practice, it will be hard to rely on this function.
   // Many classes do not properly chain -init calls.
   return obj;
}

從runtime源碼中可以看到NSObject中的init什么都沒有做。直接返回初始化后的對象。這樣處理的原因也就解釋了我們初始化對象的時候?yàn)楹我貙慽nit方法了或者initxxx自定義擴(kuò)展方法了。在重寫的init方法中,對成員變量進(jìn)行初始化,以方便后面的調(diào)用。

3、new又是怎么回事呢?

這是runtime中alloc調(diào)用的方法:

id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

這是runtime中new調(diào)用的方法:

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}

runtime中callAlloc方法的實(shí)現(xiàn):(其中有一個參數(shù)是一個可省略的并且?guī)в心J(rèn)值的參數(shù))所以兩者調(diào)用的方法就是參數(shù)的區(qū)別,最后還是走到了 [cls alloc]方法。

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
    if (slowpath(checkNil && !cls)) return nil;

#if __OBJC2__
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        // No alloc/allocWithZone implementation. Go straight to the allocator.
        // fixme store hasCustomAWZ in the non-meta class and 
        // add it to canAllocFast's summary
        if (fastpath(cls->canAllocFast())) {
            // No ctors, raw isa, etc. Go straight to the metal.
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
            id obj = class_createInstance(cls, 0);
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif

    // No shortcuts available.
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}

從runtime的源碼中可以看出,使用[xxxx alloc ]init] 與[xxx new]進(jìn)行初始化沒有太大的區(qū)別都會走 +alloc方法。
但是init可以自定義擴(kuò)展接口初始化:例如:initxxxx 而new則不能。

                                        ---------
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,675評論 1 32
  • 簡要概述 iOS創(chuàng)建對象的兩種方式: ①UIView *myView = [[UIView alloc] init...
    luckySmileBoy閱讀 807評論 0 5
  • 1.設(shè)計模式是什么? 你知道哪些設(shè)計模式,并簡要敘述?設(shè)計模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,303評論 0 12
  • 這里所要介紹的 load 與 initialize 方法,這兩個是類方法,是系統(tǒng)的方法。我曾經(jīng)見過有人在自定義的c...
    CoderHG閱讀 1,319評論 1 4
  • 每個人都拿與眾不同來標(biāo)榜自己,然后這變成了最大的相同之處,用心走進(jìn)精神病人的世界,你會忘了自己,正常的人生活已經(jīng)如...
    可愛魚魚閱讀 200評論 0 0

友情鏈接更多精彩內(nèi)容