在Objective-C中,alloc,init和dealloc是经常使用的函数,那么它们内部到底是如何实现的呢?通过查看libobjc运行时库,可以发现他们的工作原理。

  1 alloc

  alloc的功能就是为对象分配内存,关键代码如下:

  1. if (!UseGC && !zone && fast) {
  2. obj = (id)calloc(, size);
  3. if (!obj) return nil;
  4. obj->initInstanceIsa(cls, hasCxxDtor);
  5. }

  在上面的代码中,calloc就是用来位对象分配内存的,并且calloc还会将这块内存区域初始化位0,其中的size就是对象的大小=isa指针(下面介绍) + 对象中的实例变量。为了内存对齐,size的大小可能会包含一些填充字节。分配好的内存被转换为id类型,下面是运行时库中对id类型的定义:

  1. typedef struct objc_object *id;

  可以看到,id类型其实就是一个结构体指针,该结构体为objc_object,而struct objc_object的定义为(只展示了struct里面的实例变量,去掉了struct里面的方法):

  1. struct objc_object {
  2. private:
  3. isa_t isa;
  4. }

  struct objc_object中的成员变量isa是一个指针,指向的是对象所属类的Class对象。

  分配好内存之后,调用obj->initInstanceIsa方法,这个方法的作用就是用该对象所属类的Class对象地址初始化对象的isa指针,类的Class对象地址由参数cls提供。有关对象,对象所属类的Class对象的介绍,可以参看链接:刨根问底Objective-C Runtime(2)- Object & Class & Meta Class

  

  2 init

  init方法很简单,什么也不做,简单的返回对象地址,源码如下:

  1. - (id)init {
  2. return _objc_rootInit(self);
  3. }
  4.  
  5. id
  6. _objc_rootInit(id obj)
  7. {
  8. // In practice, it will be hard to rely on this function.
  9. // Many classes do not properly chain -init calls.
  10. return obj;
  11. }

  3 dealloc

  dealloc的作用就是释放内存,关键源代码如下:

  1. id
  2. object_dispose(id obj)
  3. {
  4. if (!obj) return nil;
  5.  
  6. objc_destructInstance(obj);
  7.  
  8. #if SUPPORT_GC
  9. if (UseGC) {
  10. auto_zone_retain(gc_zone, obj); // gc free expects rc==1
  11. }
  12. #endif
  13.  
  14. free(obj);
  15.  
  16. return nil;
  17. }

  object_dispose是dealloc用来释放内存所调用的函数,可以看到,object_dispose只是简单的调用了free函数来释放内存。但是在调用free之前,object_dispose调用了objc_destructInstance。objc_destructInstance函数如下:

  1. void *objc_destructInstance(id obj)
  2. {
  3. if (obj) {
  4. // Read all of the flags at once for performance.
  5. bool cxx = obj->hasCxxDtor();
  6. bool assoc = !UseGC && obj->hasAssociatedObjects();
  7. bool dealloc = !UseGC;
  8.  
  9. // This order is important.
  10. if (cxx) object_cxxDestruct(obj);
  11. if (assoc) _object_remove_assocations(obj);
  12. if (dealloc) obj->clearDeallocating();
  13. }
  14.  
  15. return obj;
  16. }

其中标红色的方法会对类中包含的成员变量进行释放,这个释放动作是由编译器来保证的(ARC下),即使overwrite了某个类的dealloc,并且overwrite dealloc时没有对成员变量赋值nil,这个过程也不受影响,照样进行。

最后附上libObjc的下载连接:https://github.com/longv2go/objc4-646

alloc & init & dealloc的更多相关文章

  1. iOS开发new与alloc/init的区别

    [className new]基本等同于[[className alloc] init]: 区别只在于alloc分配内存的时候使用了zone. 这个zone是个什么东东呢? 它是给对象分配内存的时候, ...

  2. new和alloc init的区别

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

  3. array 和 alloc init 以及 new 区别

    当你使用new.alloc或copy方法创建一个对象时,该对象的引用计数器值为1.当不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在其使用寿命结束 ...

  4. ios alloc init 和 new 的区别

    1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init] 但是并不意味着你不会接触到new,在一些代码中还是会看到[className new], ...

  5. OC 中new与alloc/init的差别

    英文具体解释:http://macresearch.org/difference-between-alloc-init-and-new 1.在实际开发中非常少会用到new.一般创建对象咱们看到的全是[ ...

  6. new与alloc/init的区别

    alloc:分配内存. init:初始化. new:代替上面两个函数:分配内存,并且初始化. 注意: 1.在实际开发中很少会用到new,一般创建对象时我们一般是 [[className alloc]i ...

  7. [转]iOS开发new与alloc/init的区别

    1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init] 但是并不意味着你不会接触到new,在一些代码中还是会看到[className new], ...

  8. Objective-C中new与alloc/init的区别

    在实际开发中很少会用到new,一般创建对象我们看到的全是[[className alloc] init],但是并不意味着你不会接触到new,在一些代码中还是会看到[className new],还有去 ...

  9. alloc init初始化后对象依然还在父视图

    self.TableView=[[UITableView alloc]init]; ........2个cell //下面但方法和addsubviews方法不一样 [self.view insertS ...

随机推荐

  1. Sql server统计查询语句消耗时间

    1. set statistics time on go  xxxx go set statistics time off 2. DECLARE @begin dateTime DECLARE @en ...

  2. js 框架及uI框架

    转载自:http://www.techweb.com.cn/network/system/2015-12-23/2245809.shtml 这篇文章主要描述现今流行的一些 Javascript web ...

  3. PHP第二课笔记

    ★Php的基本概念 快速入门案例 test.php <html> <body> //<?php  ?>是运行在服务端 <?php   echo 'hello' ...

  4. Silverlight js html 相互调用

    1.sl调用js 比如我们在页面中定义一个js函数: <script type="text/javascript">        function fnTest(ms ...

  5. form 表单练习

    创建战网通行证账号,开启您的冒险之旅.<form>    <table border="0">        <tr>            & ...

  6. js 日常问题记录

    1.解决ie6下css背景图不缓存 try{ document.execCommand('BackgroundImageCache',false,true); }catch(e){} 2.为ajax设 ...

  7. Ubuntu mysql中文乱码解决

    #vim /etc/mysql/my.cnf 找到[mysqld]添加 character-set-server = utf8 重启mysql #restart mysql mysql> sho ...

  8. EF 一对一,一对多,多对多 Flunt API 配置

       一对一 就拿后台用户权限相关的实体来说明吧,用户表,用户详细表,是一对一的关系: /// <summary> /// 用户信息类 /// </summary> publi ...

  9. keil or c51 汇编调用c语言函数 容易忽视的问题

    最近,在用keil 写一个小程序时,想实践一下从汇编调用 C语言函数,我们都知道C语言调用汇编函数讨论得较多,但反过来,从汇编中调用C语言的函数未见深入分析:在开始的时候,还是忽视了一个问题,就是对现 ...

  10. Vim 默认开启行号、语法显示等设置

      在终端下使用vim进行编辑时,默认情况下,编辑的界面上是没有显示行号.语法高亮度显示.智能缩进等功能的.为了更好的在vim下进行工作,需要手动设置一个配置文件:.vimrc. 在启动vim时,当前 ...