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

    //
    //  main.m
    
    #import <Foundation/Foundation.h>
    #import "person.h"
    /*
     堆内存的三种常见问题:
     1.野指针问题:访问没有所有权的内存,如果想安全的访问,必须确保空间还在.
     
     2.过度释放:对同一块空间释放多次,立即crash.
     
     3.内存泄露:空间使用完之后没有及时的归还系统.
     
     */
    /*
     内存管理的三种方式:
     1.垃圾回收机制(gc):由系统来管理内存,系统识别空间何时不使用,自动回收空间,不适合用于ios开发,java采用该机制
     
     2.MRC机制:是手动引用计数机制,由开发人员开辟空间,并且显示添加引用计数修改的代码,能够灵活的控制空间何时释放.
     
     3.ARC机制:自动引用计数机制是ios5.0推出的也是苹果推荐的内存管理方式,本质上还是基于MRC,只不过对于引用计数修改的代码由系统自动添加.
     
     MRC和ARC都是基于引用计数机制的
     
     
     */
    
    /*
     
     内存管理黄金法则:
     如果你对一个对象做了 alloc copy retain 操作之后你就拥有了对象的所有权,你就有责任对他进行release或者autorelease.
     简单理解就是:就看自己有没有使用alloc copy,retain这三个方法,如果使用了就对应上release或者autorelease,没有使用,就和自己无关,不用管理.
     
     *//*
     能够让对象的引用计数发生改变的方法
        
        1.alloc在堆区开辟空间,空间从无到有,引用计数从0到1;
        2.retain 将原有对象的引用计数加1.
        3.release 将原有对象的引用计数直接减1.
        4autorelease延迟减1
        5.copy.会在堆区开辟新的空间,对新的空间的计数加1,原有对象的引用计数不变.
    
     */
    
    int main(int argc, const char * argv[]) {
    //   //alloc功能两个:开辟空间;让对象的引用计数由0变1.
    //   person *per=[[person alloc]init];
    //    NSLog(@"per=%p",per);
    //    NSLog(@"per.name=%p",per.name);
    //    //retainCount:它是系统提供的方法,用来计算一个对象的引用计数
    //    //retainCount:它是MRC情况下才会有的机制,所以我们使用的时候应该将ARC改为MRC
    //    NSLog(@"per=%lu",[per retainCount]);
    //    //retain是对象的引用计数+1;
    //    
    //    [per retain];//2
    //    NSLog(@"per=%lu",[per retainCount]);
    //    [per retain];//3
    //    [per retain];//4
    //    NSLog(@"per=%lu",[per retainCount]);
    //    
    //    //release:使用对象的引用计数-1
    //    [per release];
    //    [per release];
    //    [per release];
    //   
    //    NSLog(@"per=%lu",[per retainCount]);
     
        //copy
        //对对象发送一个copy消息,对象就会找到一个方法(copywithzone)方法执行
        //copy原理:生成一个新对象,并且使新对象的引用计数为1,他不改变原始对象的引用计数
        
    //    person *per2=[per copy];
    //   // NSLog(@"per2=%lu",[per2 retainCount]);
    //    
    //    NSLog(@"per2=%p",per2);
    //    NSLog(@"per2.name=%p",per2.name);
    //    
        //[per2 release];//自动调用dealloc方法
        
    //@autoreleasepool : 自动释放池
        
        //在ios5.0后推荐使用
       // @autoreleasepool { }
        
        //[[NSAutoreleasePool alloc]init];
        
        
          
        //创建三个对象放入池子中
        //我们在使用的时候一个对象只能使用一次autorelease ,不要多次调用
        //   @autorelease他和我们release不同,autorelease是在未来某一时刻释放,而这个未来某一时刻指的是碰到自动释放池之后才会释放,而release会立即释放
    //    person *p1=[[[person alloc]init]autorelease];
    //    NSLog(@"p1=%lu",[p1 retainCount]);
    //    
    //    //系统推荐:
    //    @autoreleasepool {
    //        person *p3=[[[person alloc]init]autorelease];
    //        @autoreleasepool {
    //            person *p4=[[[person alloc]init]autorelease];
    //            NSLog(@"p4=%lu",[p4 retainCount]);
    //        }
    //        NSLog(@"p3=%lu",[p3 retainCount]);
    //    }// }相当于自动释放池释放的标记
      //自动释放池的对象被释放的时候,他里面等待的被释放的对象就会被释放
        //自动释放池是一栈的形式存在的,在池子释放的时候,会对池子里的所有对象发送一条release消息,最后进入池子的会被最先释放
        
        /*
         
         copy和retain的区别
         copy是创建一个县的对象,retain是创建一个指针,引用计数+1,copy表示两个对象的内容相同,新的对象retain为1,与旧有的对象引用计数无关,旧的对象没有发生变化,copy减少对上下文的依赖.
         retain属性表示两个对象地址相同(就是建立了一个指针,进行了指针拷贝),内容肯定相同,这个对象的retain值+1,也就是说retain是指针拷贝,copy是内容拷贝.
         
         
         */
        
        /*
         在ios中并不是所有的对象都支持copy,mutablecopy,遵守NSCopying协议的类可以发送copy消息,遵守NSMutablecopy协议的类才可以发送mutablecopy消息,假如发送了一个没有遵守上述两个协议而发送copy或者mutablecopy那么就会发生议程,但是默认的ios类并没有遵守这两个协议,如果想自定义一个copy那么就必须遵守NSCopying,并且copywithzone方法,如果项自定义一个mutablecopy那么就必须遵守NSMutablecopying,并且实现mutableCopywithzone方法
         
         */
        
       //copy:
        //浅拷贝:
        //不可变字符串,copy是浅拷贝.
    //    NSString *str=[[NSString alloc]initWithFormat:@"光光"];
    //    NSString *str1=[str copy];
    //    
    //    NSLog(@"str=%@,str1=%@",str,str1);
    //    
    //    NSLog(@"str= %lu,str1=%lu",[str retainCount],[str1 retainCount]);
    //    //深拷贝
    //    //深拷贝mutablecopy,拷贝出来的是一个可变的字符串对象
    //    NSMutableString *str3=[str mutableCopy];
    //    NSLog(@"str=%p,str3=%p",str,str3);
    //    NSLog(@"str=%lu,str3=%lu",[str retainCount],[str3 retainCount]);
    //    
    //    
        /*
         
         浅拷贝:拷贝的是指针,也就是不会申请一块新的内存空间,元对象的内存空间引用计数+1
         
         深拷贝:拷贝的内容,也就是会申请一块新的内存空间,并把原内存空间的内容拷贝进去,所以原内存空间的引用计数依然还是1,新内存空间的引用计数由0变为1
         
         */
        
        //copy深拷贝
    //    NSMutableString *Mstr=[[NSMutableString alloc]initWithFormat:@"小光"];
    //  
    //     NSString *mstr1 = [Mstr retain];
    //    
    //    NSLog(@"mstr1=%p,mstr=%p",Mstr,mstr1);
    //    
    //    
    //    NSString *mstr2=[Mstr copy];
    //    NSLog(@"mstr2=%p,Mstr=%p",mstr2,Mstr);
    //    
    //   // mutablecopy
    //    
    //    NSMutableString *mstr3=[Mstr mutableCopy];
    //     NSLog(@"mstr2=%p,Mstr3=%p",mstr2,mstr3);
    //    
        /*
         1.只有不可变字符串copy才是浅拷贝
         2.不管源字符串是否可变,质押是用 mutableCopy 出来的字符串就是可变的(深拷贝).
         */
        
        //数组内存管理:
        person *p1=[[person alloc]init];
        person *p2=[p1 copy];
        NSLog(@"p1=%p,p2=%p",p1,p2);
        NSLog(@"p1.name=%p,p2=name=%p",p1.name,p2.name);
        NSLog(@"p1=%lu,p2=%lu",[p1 retainCount],[p2 retainCount]);
        
        
        //把对象放入数组当中,对象的引用计数+1
        NSArray *array=[NSArray arrayWithObjects:p1,p2, nil];
        
        NSLog(@"p1=%lu,p2=%lu",[p1 retainCount],[p2 retainCount]);
    
        //将对象再次放到数组当中,我们数组里边的元素(对象)引用计数继续+1.
        NSMutableArray *marray=[[NSMutableArray alloc]initWithArray:array];
        
        NSLog(@"p1=%lu,p2=%lu",[p1 retainCount],[p2 retainCount]);
        
        //将对象从数组中移除,对象的引用计数-1
        [marray removeObject:p1];
        NSLog(@"p1=%lu,p2=%lu",[p1 retainCount],[p2 retainCount]);
        //对数组进行一个release操作,数组内部元素的引用计数都会-1.
        [marray release];
       NSLog(@"p1=%lu,p2=%lu",[p1 retainCount],[p2 retainCount]);
        
        
        
       [marray release];
       
        return 0;
    }
  • 相关阅读:
    iOS中Block介绍(一)基础
    iOS消息推送机制的实现
    iOS AvPlayer AvAudioPlayer音频的后台播放问题
    git 解决fatal: Not a git repository
    执行git命令出现 xcrun: error:
    ios UIView的clipsTobounds属性
    UIWindow的层级问题Level
    解决方案:The file * couldn't be opened because you don't have permission to view it
    NSString 中包含中文字符时转换为NSURL
    UIView动画
  • 原文地址:https://www.cnblogs.com/huyibo/p/5475347.html
Copyright © 2011-2022 走看看