iOS底層原理 01 : alloc&init

alloc的底層調(diào)用

1. alloc 會調(diào)用_objc_rootAlloc
+ (id)alloc {
  return _objc_rootAlloc(self);
}
2._objc_rootAlloc會調(diào)用callAlloc(cls, false, true);
id _objc_rootAlloc(Class cls)
{
  return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

3.預(yù)編譯階段,fastpath() 告訴系統(tǒng)大概率會執(zhí)行下面的過程尔苦,即:_objc_rootAllocWithZone(cls, nil)

static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
  if (slowpath(checkNil && !cls)) return nil;
  if (fastpath(!cls->ISA()->hasCustomAWZ())) {
      return _objc_rootAllocWithZone(cls, nil);
  }
#endif

  // No shortcuts available.
  if (allocWithZone) {
      return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
  }
  return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}

4.接下來執(zhí)行_class_createInstanceFromZone(cls, 0, nil,OBJECT_CONSTRUCT_CALL_BADALLOC)
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);
}
5._class_createInstanceFromZone這里是具體干的事情

1.需要開辟多少空間 size = cls->instanceSize(extraBytes);
2.申請內(nèi)存空間 obj = (id)calloc(1, size)
3.將這段內(nèi)存空間與isa關(guān)聯(lián) obj->initInstanceIsa(cls, hasCxxDtor);
4.返回指向該段內(nèi)存地址的指針 if (fastpath(!hasCxxCtor)) {return obj;}

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());

  // 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:要開辟多少內(nèi)存
  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;怎么去申請內(nèi)存
      obj = (id)calloc(1, size);
  }
  if (slowpath(!obj)) {
      if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
          return _objc_callBadAllocHandler(cls);
      }
      return nil;
  }

  // 3: 將這段內(nèi)存空間與isa關(guān)聯(lián) 
  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);
  }
  // 4: 返回指向該段內(nèi)存地址的指針
  if (fastpath(!hasCxxCtor)) {
      return obj;
  }

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

alloc流程圖

alloc流程圖

init底層調(diào)用

返回self

+ (id)init {
    return (id)self;
}

new的底層調(diào)用

1.[callAlloc(self, false) init]其實就是 [[XXX alloc]init]
2. 但是一般開發(fā)中并不建議使用new,主要是因為有時會重寫init方法做一些自定義的操作,用new初始化無法走到重寫init的自定義的部分赡若,因為new是直接調(diào)用底層的C函數(shù)去實現(xiàn)的列赎。

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

面試題

1.分析以下代打印的結(jié)果
LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [p1 init];
LGPerson *p3 = [p1 init];
LGNSLog(@"%@ - %p - %p",p1,p1,&p1);
NSLog(@"%@ - %p - %p",p2,p2,&p2);
NSLog(@"%@ - %p - %p",p3,p3,&p3);

打印的結(jié)果:


結(jié)果

分析:
1.首先p1=p2=p3 扣溺,是同一個對象骇窍,占據(jù)同一段內(nèi)存空間,所依打印出來的地址相同
2. &p1 &p2 &p3 但是指向同一段內(nèi)存空間的指針是不同的,所以 &p1 &p2 &p3不同

分析圖.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娇妓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子活鹰,更是在濱河造成了極大的恐慌哈恰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件志群,死亡現(xiàn)場離奇詭異着绷,居然都是意外死亡,警方通過查閱死者的電腦和手機锌云,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門荠医,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桑涎,你說我怎么就攤上這事彬向。” “怎么了攻冷?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵娃胆,是天一觀的道長。 經(jīng)常有香客問我等曼,道長里烦,這世上最難降的妖魔是什么凿蒜? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮胁黑,結(jié)果婚禮上废封,老公的妹妹穿的比我還像新娘。我一直安慰自己丧蘸,他們只是感情好漂洋,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著触趴,像睡著了一般氮发。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冗懦,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天爽冕,我揣著相機與錄音,去河邊找鬼披蕉。 笑死颈畸,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的没讲。 我是一名探鬼主播眯娱,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼爬凑!你這毒婦竟也來了徙缴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嘁信,失蹤者是張志新(化名)和其女友劉穎于样,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潘靖,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡穿剖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卦溢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糊余。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖单寂,靈堂內(nèi)的尸體忽然破棺而出贬芥,到底是詐尸還是另有隱情,我是刑警寧澤宣决,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布誓军,位于F島的核電站,受9級特大地震影響疲扎,放射性物質(zhì)發(fā)生泄漏昵时。R本人自食惡果不足惜捷雕,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壹甥。 院中可真熱鬧救巷,春花似錦、人聲如沸句柠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溯职。三九已至精盅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谜酒,已是汗流浹背叹俏。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僻族,地道東北人粘驰。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像述么,于是被迫代替她去往敵國和親蝌数。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354