ios内存管理

来源:互联网 发布:中国流浪汉数据 编辑:程序博客网 时间:2024/05/21 17:05

内存管理

1.每次alloc的时候,你创建的那一块内存的引用计数就会加一,切记是内存的引用计数,而不是对象的使用次数。

2.当你copy的是时候,你copy出来的对象的引用计数变为1,而原来的内存的引用计数原来是多少还是多少。

3.当returnCount减到0的时候,会自动调用dealloc函数。一般不建议自己去调用dealloc函数。此时虽然returnCount为0,但是内存里边的数据还是存在的。

4.当returnCount为0的时候,编译器只能打印出1。要判断是不是为0,可以再dealloc函数中输出一下,如果有输出,那代表此时内存的returnCount是0。

5.NSString * p = [[NSString alloc]init];
    NSLog(@"%u",[p retainCount]);    
    NSString * p2 = [p1 retain];
    NSLog(@"%d",[p retainCount]); 

打印结果是2012-08-16 19:43:37.747 类目[4255:14503] 4294967295
                    2012-08-16 19:43:37.781 类目[4255:14503] -1
此时内存开辟在常量区,会打印出一个很大的数。

    NSString * p = [[NSString alloc]initWithFormat:@"dfew"];
    NSLog(@"p = %u",[p retainCount]);   //p的count为1,开辟了一块空间
    NSString* p1 = [p retain];                   //p1和p指向同一块内存地址
    NSLog(@"p = %u",[p retainCount]);  //p1和p同时指向同一块地址,所以p1和p的count都为2
     NSLog(@"p1 = %u",[p1 retainCount]);
    NSString * p2 = [p1 retain];                 //p2指向p1的地址,所以此时有3个指针指向同一块内存
    NSLog(@"p = %u",[p retainCount]);   //此时p,p1,p2的count都是3
    NSString * p3 = p2;                           //  retain的时候引用计数才会加1
    NSString * p4 = p3;         //只是简单的赋值。count不会改变。p3和p4可认为是为指针,也可以访问同一块内存,但是当count为0的时候就不能用了
     NSLog(@"p = %u",[p retainCount]);   //3
    NSLog(@"p4 = %u",[p4 retainCount]);//3
    [p4 release];
    NSLog(@"p = %u",[p retainCount]);  //用p3,p4,p..都可以释放内存。此时count为2。
    [p1 release];
    [p2 release];       //此时自动调用dealloc函数,这是系统的类,可以用类目重写NNString的dealloc函数

 6.属性的内存管理

6.1  

assin不能加引用计数。

assin 的内部实现

-(void)setStu:(Student *)s

{

      stu = s;    直接赋值引用计数不加1

}

6.2

retain的内部实现

-(void) setStu:(Student *)s

{

     if(stu!=s)     判断老的是不是和新的指向同一地方

      {

         [stu relese];    当新开辟的一个内存的时候,里边为空,对空操作相当什么都不做。当stu原来已经指向一个内存,此时他原来指向的内存的count-1。

         [s retain];   让新内存的count+1,为了防止数据丢失。

         stu  = s;      简单的指向同一地址

      }

}

例如用@property(nonatomic,retain)NSString * name; 声明一个属性name

    Student * stu1 = [[Student alloc] init];

    NSString * name1 = [[NSStringalloc] initWithFormat:@"zhangsan"];

    stu1.name = name1; 

    NSLog(@"name1 = %d",[name1 retainCount]);  此时为2,因为在用属性的时候[name1 retain]了

     NSLog(@"stu1 = %d",[stu1 retainCount]);   stu1的count还是1,因为上边对nil操作的相当于什么都不做

      NSString * name2 = [[NSString alloc] initWithFormat:@"lisi"];
    stu1.name = name2; //stu1指向新的内存地址
    NSLog(@"name2 = %d",[name2 retainCount]);//2
    NSLog(@"name1 = %d",[name1 retainCount]);//因为[stu1 release] 所以原来name1的count-1 = 1
    [name1 release];      //此时name1内存彻底释放,所以在dealloc函数中的[self.name  release] 是为了释放最后一个(这里是让name2的count-1 = 0)。
     NSLog(@"name1 = %d",[name1 retainCount]);
     NSLog(@"name1 = %d",[name2 retainCount]);//2

    stu1.name = name2; //stu1指向新的内存地址

    NSLog(@"name2 = %d",[name2 retainCount]);//2

    NSLog(@"name1 = %d",[name1 retainCount]);//因为[stu1 release] 所以原来name1的count-1 = 1

    [name1 release];      //此时name1内存彻底释放,所以在dealloc函数中的[self.name  release] 是为了释放最后一个(这里是让name2的count-1 = 0)。

     NSLog(@"name1 = %d",[name1 retainCount]);

     NSLog(@"name1 = %d",[name2 retainCount]);//2

    stu1.name = name2; //stu1指向新的内存地址

    NSLog(@"name2 = %d",[name2 retainCount]);//2

    NSLog(@"name1 = %d",[name1 retainCount]);//因为[stu1 release] 所以原来name1的count-1 = 1

    [name1 release];      //此时name1内存彻底释放,所以在dealloc函数中的[self.name  release] 是为了释放最后一个(这里是让name2的count-1 = 0)。

     NSLog(@"name1 = %d",[name1 retainCount]);

     NSLog(@"name1 = %d",[name2 retainCount]);//2

    [name2 release];有一个alloc就要有一个release与之对应  ,此时为1,在dealoc中释放为0


7.  NSAutoreleasePool

1.自动释放池。
2.创建的对象某个时候销毁时,可以使用对象的autorelease。
3.对象把所有权管理给最近的NSAutoreleasePool对象,并由其全权管理
4.当 池  对象drain或release时候,会逐一对 池  内的对象发送release消息
5.除非必要,否则不建议使用
6.专门处理便利构造器
便利构造器当中最后  return [sut  autorelease];
NSAutoreleasePool * pool = [[NSAutoreleasePool]  init];
、、、要释放的东西。。。。
[pool release];        //[pool drain],,把里边的东西清空,内存还留着


8.只要有alloc就要有release,不管是不是真的开辟了空间

比如:   

 NSString * str = [[NSString alloc]initWithString:@"yid"];  虽然不会开辟空间,但是也要release。系统内部会实现,不会过度释放

0 0