zoukankan      html  css  js  c++  java
  • OC 内存管理

    本章介绍如何使用OC和Cocoa进行内存管理。

    OC2有垃圾回收机制。

    1、对象生命周期

    1.1、引用计数

    Cocoa采用一种称为引用计数(reference counting)的技术,有时也叫做保留计数

    每个对象有一个与之相关的整数,称作它的引用计数器或保留计数器。当某段代码需要访问一个对象时,该代码将该对象的保留计数器值加1,表示“我要访问该对象”。当这段代码结束对象访问时,将对象的保留计数器值减1,表示它不再访问该对象。当保留计数器值为0时,表示不再有代码访问该对象了,因此该对象将被销毁,其占用的内存被系统回收以便重用。

    当使用alloc、new方法或者通过copy消息(生成接收对象的一个副本)创建一个对象时,对象的保留计数器值被设置为1.要增加对象的保留计数器值,可以给对象发送一条retain消息。要减少对象的保留计数器值,可以给对象发送一条release消息。

    当一个对象因其保留计数器值归0而被销毁时,OC自动向对象发送一条dealloc消息。可以在自己的对象中重写dealloc方法。一定不要直接调用dealloc方法。可以利用OC在需要销毁对象时调用dealloc方法。要获得保留计数器的当前值,可以发送retainCount消息。

    - (id) retain;

    - (void) release;

    - (unsigned) retainCount;

    retain方法返回一个id类型的值。通过这种方式,可以嵌套执行带有其它消息发送参数的保留调用,增加对象的保留计数器值并要求对象完成某种操作。如,[[car retain] setTire: tire atIndex: 2];

    1.2、对象所有权

    object ownership,当某个实体“拥有一个对象”时,就意味着该实体要负责确保对其拥有的对象进行清理。

    如果一个对象具有指向其它对象的实例变量,则称该对象拥有这些对象。如果一个函数创建了一个对象,则称该函数拥有它创建的这个对象。

    当多个实体拥有某个特定对象时,对象的所有权关系更复杂了。

    1.3、访问方法中的保留和释放

    2、自动释放

    2.1、所有对象全部入池

    Cocoa中有一个自动释放池(autorelease pool)的概念。NSAutoreleasePool

    它是一个存放实体的池(集合),这些实体可能是对象,能够被自动释放

    NSObject类提供了一个autorelease方法

    - (id) autorelease;

    该方法预先设定了一条在将来某个时间发送的release消息,其返回值是接收消息的对象。retain消息采用了相同的技术,使嵌套调用更加容易。当给一个对象发送autorelease消息时,实际上是将该对象添加到NSAutoreleasePool中。当自动释放池被销毁时,会向该池中的所有对象发送release消息。

    可以很好地管理内存的description方法:

    - (NSString *) description

    {

      NSString *description;

      description=[[NSString alloc] initWithFormat: @"i am %d years old",4];

      return ([description autorelease]);

    }

    NSLog(@"%@",[someObject description]);

    2.2、自动释放池的销毁时间

    自动释放池什么时候被销毁,以便可以向其包含的所有对象发送release消息?什么时候创建自动释放池呢?

    在我们一直使用的Foundation库工具中,创建和销毁自动释放池的方法非常明确:

    NSAutoreleasePool *pool;

    pool=[[NSAutoreleasePool alloc] init];

    ...

    [pool release];

    创建一个自动释放池时,该池自动成为活动的池。释放该池时,其保留计数值归0,然后该池被销毁。销毁过程中,该池释放所包含的所有对象。

    当使用AppKit时,Cocoa定期自动为你创建和销毁自动释放池。通常是在程序处理完当前事件(如鼠标单击或按键)以后执行这些操作。可以使用任意多的自动释放对象,当不再使用它们时,自动释放池将自动为你清理这些对象。

    2.3、自动释放池的工作过程

    首先创建一个自动释放池:

    NSAutoreleasePool *pool;

    pool=[[NSAutoreleasePool alloc] init];

    现在任何时候向一个对象发送autorelease消息,该对象都会被添加到这个自动释放池中:

    最后销毁自动释放池,NSAutoreleasePool当作一个普通对象release:

    [pool release];

    3、Cocoa内存管理机制

    现在已经学习了一些内存管理方法:retain、release、autorelease。

    Cocoa有许多内存管理约定,它们都是一些很简单的规则,可一致地应用于整个工具包。

    这些规则如下:

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

    2)当你通过任何其它方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。

    3)如果你保留了某个对象,你需要(最终)释放或自动释放该对象,必须保持retain方法和release方法的使用次数相等。

    3.1、临时对象

    如果使用new、alloc或copy方法获得一个对象,则需要安排该对象的死亡。

    如果使用任何其它方法获得一个对象,例如arrayWithCapacity:方法,则不需要关心如何销毁该对象。

    arrayWithCapacity: 方法不属于alloc、new、copy这三个方法中的一个,因此可以假设该对象被返回时保留计数器值为1且已经被设置为自动释放1.

    3.2、拥有对象

    通常,你可能希望在多个代码行中一直拥有某个对象。常见的方法是:在其他对象的实例变量中使用这些对象,将他们加入到诸如NSArray或NSDictionary等集合中,或者将其作为全局变量使用。

    如果你使用除alloc、new或copy以外的方法获得一个对象,你需要保留该对象。考虑编写GUI应用程序时事件循环的情况。你希望保留自动释放的对象,使这些对象在当前的事件循环结束以后仍能继续存在。

    3.3、垃圾回收

    OC2.0引入了自动内存管理机制,也称垃圾回收。

    对于已经创建和使用的对象,当你忘记清理它们时,系统会自动识别哪些对象仍在使用,哪些对象可以回收。启用垃圾回收非常简单,只不过这是一种可选择启用的功能。

    启用垃圾回收以后,通常的内存管理命令全部都变成了空操作指令,不执行任何操作。

    OC的垃圾回收器是一种继承性的垃圾回收器。与那些已经存在了一段时间的对象相比,新创建的对象更可能被当成垃圾。垃圾回收器定期检查变量和对象以及它们之间的指针,当发现没有任何变量指向某个对象时,就将该对象视为应该被丢弃的垃圾

    如果在一个实例变量中指向某个对象,一定要在某个时候使将该实例变量赋值为nil,已取消对该对象的引用并使垃圾回收器知道该对象可以被清理了。

    与自动释放池一样,垃圾回收器也是在事件循环结束时触发的。当然,如果不是编写GUI程序,也可以自己触发垃圾回收器。

    如果开发iPhone软件,则不能使用垃圾回收。实际上,在编写iPhone程序时,苹果公司建议不在自己的代码中使用autorelease方法,同时还要避免使用创建自动释放对象的便利函数。

  • 相关阅读:
    poj2976 Dropping tests (01分数规划)
    bzoj5281/luogu4377 Talent Show (01分数规划+背包dp)
    bzoj5280/luogu4376 MilkingOrder (二分答案+拓扑序)
    bzoj1492/luogu4027 货币兑换 (斜率优化+cdq分治)
    [模板]树状数组
    匿名函数 python
    yield解析你要知道的源自IBM
    stackoverflow yield 帖子
    pandas 生成器,生成大数据
    pd.contact,dataframe 拼接
  • 原文地址:https://www.cnblogs.com/cjj-ggboy/p/13039914.html
Copyright © 2011-2022 走看看