• Objective-C内存管理


    1. Objective-C指针赋值时,retainCount不会自动增加,需要手动retain。

    1 ClassA *obj1 = [[ClassA alloc] init];       //retain count = 1 
    2 ClassA *obj2 = obj1;                             //retain count = 1 
    3 [obj2 retain];                                         //retain count = 2 
    4 [obj1 hello];                                           //输出hello     
    5 [obj1 release];                                     //retain count = 2 – 1 = 1 
    6 [obj2 relese];             //retain count = 0,对象被销毁                          

    2. 新生成的对象只要调用autorelease就行了,无需再调用release!自动释放的对象不需要调用release,因为已经将释放的责任转交给了自动释放池。但是对于赋值的指针还是要调用release的!

    1 ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 
    2 ClassA *obj2 = obj1;     //retain count = 1 
    3 [obj2 retain];     //retain count = 2 
    4 [obj1 hello];     //输出hello 
    5                         //对于obj1,无需调用(实际上不能调用)
    6 release [obj2 hello];     //输出hello 
    7 [obj2 release];     //retain count = 2-1 = 1

    3. NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄露。

    而自动释放池之间以栈的形式实现:当你创建了一个新的自动释放池时,它被添加到栈顶。接受autorelease消息的对象将被放入最顶端的自动释放池中。如果将一个对象放入一个自动释放池中,然后创建一个新的自动释放池,再销毁新建的自动释放池,则这个自动释放池对象仍将存在,因为容纳该对象的自动释放池仍然存在。

    4. Objective-C程序中可以嵌套创建多个autorelease pool。在需要大量创建局部变量的时候,可以创建内嵌的autorelease pool来及时释放内存。一般都是使用完对象之后马上进行释放,以将内存使用量保持在尽可能低的水平。

    5. 如果你通过alloc、new或copy来创建一个对象,如果是临时对象,那么你必须在不再使用时手动调用release或autorelease来释放对象;如果希望在多段代码中一直拥有对象,作为其他对象的实例来使用,则只需确保在拥有该对象的dealloc方法中释放它即可。除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。

    6. retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。

    7. 范式:Release一个对象后,立即把指针清空(顺便说一句,release一个空指针是合法的,但不会发生任何事情)。

    1 [obj1 release]; 
    2 obj1 = nil;
    1 ClassA *obj2 = obj1; 
    2 [obj2 retain]; 
    3 //do something 
    4 [obj2 release]; 
    5 obj2 = nil;

    8. 范式:在方法中创建的临时对象,在方法返回前需要对其进行释放。

    在一个函数创建并返回对象,需要把这个对象设置为autorelease。这样,由于延迟释放,返回的对象不仅有效,而且保证会被自动释放池释放。

    1 ClassA *Func1() 
    2 3      ClassA *obj = [[[ClassA alloc]init]autorelease];  
    4      return obj; 
    5 }

    如果程序的某个方法中需要创建很多临时对象,当方法执行完之后这些临时对象就没用了。如果整个程序只有一个释放池,则这些临时对象会一直无法释放,直至事件处理结束。所以,可以方法的开始处或循环中创建一个局部的自动释放池,在方法返回或退出循环之前释放自动释放池。这样所有该方法创建的临时对象会随着自动释放池的释放而释放。使用@autoreleasePool{},无须显示向某对象发送autorelease方法,所有花括号里的代码都会被自动放入这个新池子里,任何在花括号里定义的变量在括号外就无法使用了。

     1 int main (int argc, const char *argv[]) 
     2 { 
     3      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     4      int i, j; 
     5      for (i = 0; i < 100; i++ ) 
     6      { 
     7          @autoreleasePool
     8          {
     9           for (j = 0; j < 100000; j++ ) 
    10              [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。 
    12 } 13 } 14 return (0); 15 } // main

    9. 范式:在子类的dealloc方法中调用基类的dealloc方法 。

    1 -(void) dealloc 
    2 { 
    3 4         [super dealloc]; 
    5 }

    10. 范式:如果类中声明了具有保持copy和复制retain特性的属性,则需要在dealloc方法中release其成员变量

     1 @interface ClassA : NSObject 
     2  3         ClassB* _objB; 
     4 }   
     5 @property (retain) ClassB* objB; 
     6 @end   
     7 
     8 @implementation ClassA 
     9 @synthesize objB; 
    10 -(void) dealloc 
    11 12         [_objB release];
    13         [super dealloc]; 
    14 15 @end

    11. 范式:除了dealloc方法以外,始终用.操作符的方式来调用property。 

    1 self.objB 或者 objA.objB

    12. 自己管好自己就行。如果获得了一个其他方法提供的对象,则不需要考虑该对象的内存管理问题,不必执行任何操作。但是,如果想要在一段时间内使用该对象,则需要保留retain该对象,并在使用完成后(在dealloc方法中)将其释放release。必须保持retain方法和release方法的使用次数相等。

     

  • 相关阅读:
    BOM,文档宽高及窗口事件小析
    表格、表单操作
    DOM相关属性,方法,兼容性问题处理小析
    js回调函数,字符串,数组小析
    js中return,this,arguments,currentStyle和getComputedStyle小析
    JS作用域,浏览器解析原理
    JS中注意事项
    PS中常用快捷键
    javaweb之框架标签(day1 框架标签的使用)
    网络编程课程复习
  • 原文地址:https://www.cnblogs.com/fuleying/p/3474517.html
Copyright © 2020-2023  润新知