Objective-C:内存管理的小结

内存管理:

1、OC的对象都是分配在堆里的
     Perosn *person  = [[Person alloc]init];
     Person *person       //指针类型的变量,放在栈里。
     [[Person alloc]init]   //在堆里创建的对象,并初始化。
     真正的含义: 用指针变量指向了堆中创建出来的对象
 
     Person *person2 = person; //person2和person都指向了同一个对象
 
2、堆里的对象应该是谁创建,就该是谁释放。系统释放模式分为两种:
     ARC 自动引用计数 (系统帮助完成内存的释放)
     MRC 手动引用计数 (人为帮助完成内存的释放)
MRC:

对于对象类型的实例变量,可以使用@property自动生成相应地存取方法,

但@property中必须要采用retain的内存设置;

assign用于基本的数据类型,不需要获取所有权的类型。

 ARC:

 strong 相当于MRC中的retain

 assign 用于基本的数据类型

 weak   不需要获取所有权的对象类型

 unsafeunretain 用在不支持weak的旧版本中

     
3、什么是引用计数?
     程序中会出现多个指针指向同一个对象的情况。这种情况下要保证不能提前释放这个对象,必须在所有的指针都不再使用这个对象时候才能释放对象。
     计数器:retainCount     -(unsigned)retainCount;
     对象中存储被引用的次数,
     当被引用的时候,计数器加1;  -(id)retain;    retainCount+1
     不在引用的时候,计数器减1;  -(void)release;   retainCount-1
     当计数器为0的时候,真正去销毁对象。-(void)dealloc; //可以重写这个方法,但是切记不要直接显式的调用,因为系统在最后会直接调用它,此时retainCount=0
 
4、对象所有权
       指针指向一个对象时,可以获得对象所有权(引用计数器加1);
       也可以不获得对象所有权(引用计数器不变化)
      ARC:strong,weak,assign       strong获得对象所有权
      MRC:retain ,assign        retain获得对象所有权
 
5、引用计数和字符串
内存中的常量字符串的空间分配与其他对象不同,他们没有引用计数机制
凡是自定义的对象都有引用计数机制;
OC内部中对象分为可变对象(NSMutableString等)和不可变对象(NSString、NSArray等),
   不可变对象不适用于引用计数的机制,可变的对象适用引用计数机制。
 
6、对象之间的循环引用
       两个对象A、B,有可能会出现一种特殊的情况:A中包含B的实例变量;B中又包含A的实例变量,如果两个实例变量都是强引用(A有B实例变量的所有权,B也有A的实例bl的所有权),然后再两个对象销毁时,会出现A、B都不能正常销毁的情况。
 
7、对象复制

对象复制中的浅复制和深复制:

浅复制:复制对象时,如果对象中包含对象类型的实例变量,只是复制指针。新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是同一个对象。任何一方实例变量对对象做修改,另一方实例变量指向的该对象也就改变了。

深复制:复制对象时,如果对象中包含对象类型的实例变量,要对对象类型的实例变量也要做对象复制。新对象中的对象类型实例变量和旧对象中的对象类型实例变量指的是不同的对象。不管任何一方实例变量对对象做修改,都互相不影响对方所指向的对象的内容。

用网上一哥们通俗的话将就是:

浅复制好比你和你的影子,你完蛋,你的影子也完蛋

深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。

8、自动释放池(管理需要延迟释放的对象)

由new、copy、alloc创建的对象不会自动入池,需要通过发送autorelease消息,将一个对象添加到其中,以便最后释放:[MyFranction autorelease]

 

 1 #import <Foundation/Foundation.h>
 2 #import "Book.h"
 3 void ex1();
 4 void ex2();
 5 void ex3();
 6 void ex4();
 7 void ex5();
 8 int main(int argc, const char * argv[])
 9 {
10     //ex1();
11     //ex2();
12     //ex3();
13     //ex4();
14     ex5();
15     return 0;
16 }

 

 

 

1)创建自动释放池的两种方法:

-NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]

[pool release]《==等价于==》[pool drain]; 

 1 void ex1()
 2 {
 3     //创建一个自动释放池对象
 4     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
 5     //自动释放池的使用
 6     Book *book = [[Book alloc]initWithTitle:@"OC" andAuthor:@"Jobs" andPrice:35.6];
 7     
 8     //将book对象加入自动释放池
 9     [book autorelease];
10     [book print];
11     
12     NSLog(@"autorelease last");
13     //清空自动释放池--会给每个管理的对象发送release消息
14     [pool release];//===[pool drain]
15 }

 

或者

-@autoreleasePool

{

}

 1 //创建自动释放池的第一种方式
 2 void ex2()
 3 {
 4     @autoreleasepool {
 5 
 6     //自动释放池的使用
 7     Book *book = [[Book alloc]initWithTitle:@"OC" andAuthor:@"Jobs" andPrice:35.6];
 8     
 9     //将book对象加入自动释放池
10     [book autorelease];
11     [book print];
12     
13     NSLog(@"autorelease last");
14     }//在自动释放池结束时,会给每个管理的对象发送release消息
15 }

 

(2)延迟释放对象

在OC的内置类(NSString、NSArray等)中提供的类方法创建的对象实例都是“延迟释放对象”,也就是在对象创建完成后将对象加入自动释放池。

 

1 +(Book*)bookWithTitle:(NSString*)title andAuthor:(NSString*)author andPrice:(CGFloat)price
2 {
3     return [[[Book alloc]initWithTitle:title andAuthor:author andPrice:price]autorelease];
4 }

 

1 void ex3()
2 {
3     @autoreleasepool {
4         //这种对象不需要我们去给它们发release消息。
5         Book *book = [Book bookWithTitle:@"OC" andAuthor:@"Jobs" andPrice:35.6];
6         [book print];
7         //[book release];
8     }
9 }

 

 

(3)自动释放池的嵌套

    对象在加入自动释放池时,加入的是离它最近的自动释放池,目的是为了让延迟释放的对象尽快得到释放,降低程序运行期间的内存占用;

           在管理多个自动释放池时,采用了类似“栈”的结构,可以让对象轻松的找到离它最近的(栈顶的)自动释放池。

 

1 +(Book*)bookWithTitle:(NSString*)title andAuthor:(NSString*)author andPrice:(CGFloat)price
2 {
3     return [[[Book alloc]initWithTitle:title andAuthor:author andPrice:price]autorelease];
4 }

 

 

 

 1 void ex4()
 2 {
 3     @autoreleasepool {
 4         Book *book = [Book bookWithTitle:@"iOS" andAuthor:@"Bill" andPrice:55.6];
 5         [book print];
 6         @autoreleasepool {
 7             Book *book2 = [Book bookWithTitle:@"iOS" andAuthor:@"Bill" andPrice:55.6];
 8             [book2 print];
 9         }
10     }
11 }

 

(4)独立的自动释放池

  当程序中出现创建大量延迟释放对象的代码时,最好给它一个独立的自动释放池,保证这些对象在不用了后马上释放掉

1 +(Book*)bookWithTitle:(NSString*)title andAuthor:(NSString*)author andPrice:(CGFloat)price
2 {
3     return [[[Book alloc]initWithTitle:title andAuthor:author andPrice:price]autorelease];
4 }

 

 1 void ex5()
 2 {
 3     @autoreleasepool {
 4         for(int i=0; i<10000; i++)
 5         {
 6             @autoreleasepool {//独立的自动释放池
 7                 Book *book = [Book bookWithTitle:[NSMutableString stringWithFormat:@"book%d",i+1] andAuthor:[NSMutableString stringWithFormat:@"author%d",i+1 ] andPrice:20+i];
 8                 [book print];
 9             }
10         }
11     }
12 }

 

 

   

posted @ 2015-08-14 16:04  XYQ全哥  阅读(251)  评论(0编辑  收藏  举报