• OC_内存管理


     
    引言:
         1、OC中的对象都是分配在堆中的
                   声明对象的格式:
                        Person *person = [Person new];
                        Person *person           //指针类型的变量是放在栈里面的;
                        [Person new]               //在堆创建对象并初始化;                    
                        /*用指针变量指向了堆中创建出来的对象*/
                        Person *person2 = person;
                        /*person2/person都指向了同一个对象*/
         2、堆里的对象应该谁创建、谁释放
              ARC     自动引用计数
                MRC    手动引用计数
         3、什么是引用计数?
               在程序当中出现多个指针指向同一个对象的情况。在这种情况下要保障不能提前释放这个对象,必须是所有指针都不再使用这个对象的时候才能释放对象。
              对象中存储被引用的次数,当被引用时候计数器加1,不再引用时计数器减1,当计数器为0的时候,真正销毁对象。
         4、对象所有权
              指针在指向一个对象时,可以获得对象所有权(引用计数会加1);也可以不获得对象所有权(引用计数不发生变化)。
              ARC:strong、weak、assign。
              MRC:retain、assign。 
     
    dealloc 是用来销毁对象所占的内存,而release是用来使对象的引用计数减一
     
    总结:
    内存管理、实例变量
    1、为何引用内存管理?
    内存管理是程序设计中常见的资源管理的一部分。每个计算机系统可供程序使用的资源都是有限的,这些资源包括内存、打开文件数量以及网络连接等。如果你使用了某种资源,例如因打开文件而占用了资源,那么你需要随后进行清理。如果你不断打开文件并且保持打开状态而且不去关闭,最终将无法打开新的文件。摄像一下公共图书馆的场景。任何人都只借不还,最终图书馆将会因无书而倒闭,每个人都无法再使用图书馆。
    1)对象生命周期
    对象的生命周期包括诞生(通过alloc或new方法实现)、生存(接收消息和执行操作)、交友(借助方法的组合和参数)以及当他们的生命结束时最终死去(释放)。当对象的生命周期结束时,他们的源材料(内存)将被回收以供新的对象使用。
    2)引用计数
    Cocoa采用了一种称为引用计数的技术,有时也叫做保留计数。每个对象有一个与之相关联的整数,称作为引用计数器或保留计数器。当某段代码需要访问一个对象时,该代码将该对象的保留计数器加1,表示“我要访问该对象”。当这段代码结束对象访问时,将对象的保留计数器值减1,表示不再访问该对象。当保留计数器值为0时,表示不再有代码访问该对象了,因此对象将被销毁,其占用的内存被系统回收以便重用。
    当使用alloc、new方法或者通过copy消息(生成接收对象的一个副本)创建一个对象时,对象的保留计数器值被设置为1.
    以下:retainCount会加1;
    1. 1.Person *person =[ [Person alloc]init];
    2. 2.Person *person = [Person new];
    3. 3.NSMutableString *array = [NSMuatbleString stringWithString :@“”];
    4.   [array setObjetct:person];
    5. 4、[person retain];
    注意:Person *person2 = person; //不会获得对象所有权
    以下:retainCount会减1:
    1. 1.[person release];
    2. 2.[array removeObject:person];
     
    2、Cocoa内存管理规则
    1.如果使用new、alloc或copy操作获得一个对象,则该对象的保留计数器值为1.
    2.如果通过任何其他方法获得一个对象,则假设该对象的保留计数器值为1,而且已经被设置为自动释放。
    3.如果保留了某个对象,则必须保持retain方法和release方法的的使用次数相等。
     
     
    代码注意:
    1.self指向的是实例的一个指针,不能在类方法中使用
    1. +(Person *)personWithName:(NSString *)name andAge:(NSInteger)age
    2. {
    3. self = [super init];
    4. if(self)
    5. {
    6. _name = name;
    7. _age = age;
    8. }
    9. return self;
    10. }
    2.类方法:
    1)在类方法中,由于还没有创建对象实例,所以:self指针不能使用;一般类方法这么使用:

    /*类方法:

         1.在类方法中,由于还没有创建对象实例,所以:self指针不能使用;

         2.实例变量不能在类方法中使用;*/

    1. +(Person *)personWithName:(NSString *)name andAge:(NSInteger)age
    2. {
    3.      //类方法是通过类名使用的,没有创建对象实例变量
    4.      return [[Person alloc]initWithName:name andAge:age];
    5.      //类方法中的返回是具体的类型;
    6. }
    2)实例变量不能在类方法中使用;
    3)dealloc在释放是自动调用,创建对象时是先创建基类部分,然后创建子类部分;销毁时先从子类销毁,然后销毁基类;ARC禁止显示发送deallo消息;
    3、不可变对象不适用于引用计数
    1.不可变对象是可变对象的基类
    2.类中的对象型成员变量,他的set方法要保证获得对象所有权
    1. -(void)setName:(NSString *)name
    2. {
    3.    if(_name != name )
    4.   {
    5.     //要将原来对象的所有权释放掉
    6.     [_name release];
    7.     //在获得新的对象的所有权
    8.   _name = [name retain];//保留一个name的计数,获得所有权;
    9.   }
    10. }
    3)如果类中包含了对象类型的成员变量,必须重写dealloc方法,保证对象类型变量的正常释放;
    1. -(void)dealloc
    2. {
    3.   [super dealloc];
    4. }
     
     附录:
    //测试手动计数
    1.         //1.创建对象会获得对象所有权
    2.         Integer *i1 = [Integer integerWithInteger:10];
    3.         NSLog(@"retainCount = %lu",[i1 retainCount]);
    4.        
    5.         //2.通过指针赋值,不获得对象所有权;
    6.         Integer *i2 = i1;//不获得对象所有权
    7.         NSLog(@"retainCount = %lu",[i2 retainCount]);
    8.        
    9.         //3.通过retain获得对象所有权
    10.         [i1 retain];//获得对象所有权
    11.         NSLog(@"retainCount = %lu",[i1 retainCount]);
    12.        
    13.         //4.将对象添加到容器中,获得对象所有权,容器中会获得对象的一个引用
    14.         NSMutableArray *arr = [NSMutableArray array];
    15.         [arr addObject:i1];
    16.         NSLog(@"retainCount = %lu",[i1 retainCount]);
    17.        
    18.         //5.通过releas释放对象所有权,
    19.         [i1 release];
    20.         NSLog(@"retainCount = %lu",[i1 retainCount]);
    21.        
    22.         //6.从容器当中删除对象,也会释放对象所有权
    23.         [arr removeObject:i1];
    24.         NSLog(@"retainCount = %lu",[i1 retainCount]);
    25.        
    26.         //7.最后再释放一次,对象才会被正常销毁
    27.         [i1 release];
     
  • 相关阅读:
    idea 访问https://start.spring.io失败
    torch.nn.Dropout()
    torch.utils.tensorboard
    PyTorch 环境配置及安装
    np.reshape()
    torch.utils.data
    np.sum()
    Pytorch model.train()、model.eval()
    np.squeeze
    Python 临时文件、目录的生成
  • 原文地址:https://www.cnblogs.com/xjf125/p/4728327.html
Copyright © 2020-2023  润新知