zoukankan      html  css  js  c++  java
  • oc 第五天(内存管理)

    OC的重点: 内存管理

    1 基本原理

        OC的内存回收机制是和JAVA的自动回收机制是不同的,它有两种模式,或者准确的说是同
    一种模式的两种不同体现,下面简单总结下.

    1手动内存回收

          这是OC一直支持并在使用的内存回收机制,其主要实现和原理和C类似,遵循的是"谁使用,
    谁回收"的原则.
          在OC中创建任何对象都会拥有一个类似于计数器的属性(使用 [对象 retainCount] 查看),
    这个计数器是用来体现到底有多少个对象在使用这个对象(内存),当计数器为0的时候系统就
    会调用delloc方法直接回收内存,以下几种方法都会对计数器产生改变:

    alloc  让计数器从 0 变 1;

     

    retain 计数器 +1;

     

    copy 新开辟一块内存,把原对象的值复制;

     

    release 计数器 -1;

     

    autorelease 计数器延迟-1;


    alloc 不再解释


    retain :先看下面这段程序

     

            Person *p = [[Person alloc]initWithName:@"fds" age:12 sex:@"cfds"];
            [p retain];
            [p release];
            [p release];
      首先 alloc 计数器+1  = 1,retain一次,计数器再+1 = 2 ,release二次 -2  计数器 = 0 系统调用delloc 

    这样 这个对象才会正确的被释放掉 

      retain 又会牵扯到另一个问题,属性在Student类中定义了一个

    @property (retain)Book *book;

     

    - (void)setBook:(NSString *)book
    {
        if (_book != book) {
            [_book release];
            _book = [book retain];
        }
    }
    - (NSString *)book
    {
        return [[_book retain] autorelease];
    }
      这是系统在定义book属性后默认给我们写的setter 和 getter的代码 ,首先看setter

    当第一次为book赋值的时候 

      [_book release];

      由于_book为空 OC中对于一个为nil(null)的对象,它调用的任何方法都是无效的,所以执行

     

     _book = [book retain];
      那么book的计数器为 2 这样的话 在外面创建book对象时 release一次 然后 当下一次赋值的时候 

    会把_book首先release一次  这样就会把本次的book释放掉,而且也符合谁使用,谁回收的原则,这样

    也会产生一个问题,当Student释放时,最后一次的_book怎么释放

    if 的作用是为了防止第二次赋值同一个值


    这就牵扯到 delloc方法:

    delloc方法,是当计数器为0的时候系统自动调用的,不会手动调用,一般都会改写这个方法,把本类中定义

    过的所有对象类型的属性都release 一次,那么当student对象被回收时,所有调用的内存都被回收了.


    copy: 

    copy的使用也要牵扯到属性这个问题,

    @property (copy)Book *book;

    copy首先要实现NSCopy接口 实现里面的

     

    - (id)copyWithZone:(NSZone *)zone方法 下面是一个Person类的例子

    - (id)copyWithZone:(NSZone *)zone
    {
        Person *newPerson = [Person allocWithZone:zone];
        [newPerson setAge:[self age]];
        [newPerson setName:[self name]];
        [newPerson setSex:[self sex]];
        return newPerson;
    }
     这样就实现了copy出一个新对象的方法,调用 [person copy] 就可以了

    那么对原对象或者现对象的操作都不会互相影响了 

     在调用 Person *p2 = [person copy]; 后 release p2 就能实现对象的回

    收(p2 和 方法体内的 newPerson 指向的是同一个内存)  [ps: 又有一个知识点,指向同一个内存的指针无论有多少个,计数器都不会+1]


    当person作为一个方法的属性时 setter和getter的方法如下

     

    - (void)setPerson:(NSString *)person
    {
        if (_person != person) {
            [_person release];
           _person = [person copy];
        }
    }
    - (NSString *)person

    autorelease:



    不自动释放 而是交给 autoreleasepool (延迟释放)自动释放池 : 讲对象所有权交给最近的NSAutoreleasepool 对象

    [pool drain] 把释放池内的垃圾回收(一般不再使用)

    [pool release] 把释放池都失去

    原则上 尽可能用release

    还有一个便利构造器的内存管理

     

    +(id)personWithName:(NSString *)name age:(int)age sex:(NSString *)sex
    {
        Person *p = [[Person alloc ] initWithName:name age:age sex:sex];
        return [p autorelease];
    }
    
    { return [[_person retain] autorelease];}
    

    这个也是使用了自动释放.


    2自动管理内存(ARC ios5 新特性)

    主要实现就是上面的autorelease, ARC模式是一种自动管理内存的模式,不用手动管理.



    3内存泄露的几个情况

    内存泄露 : 只开辟 不清除

    过度释放: 释放之后还释放

    野指针:  释放后 还在使用



    补充一个@class


    @class 声明一个类,主要用于.h文件中 让文件可以声明这个对象

    等到用这个对象的方法时 再在.m 文件import

    效果: 提高编译效率(不会因某个类改变导致编译器要重新编译所有关于这个类的文件)


    这就是今天所学的了,感觉OC的内存管理是一个很是需要理解和下功夫的地方,它没有java的简便,

    却提供了比较灵活的地方 内存管理的是OC里面一个重要的地方,需要大量的练习和使用.






  • 相关阅读:
    [hihocoder-1974] 智能分包 状态压缩dp
    2018北京ICPC D. Frog and Portal 斐波那契数 构造
    [hdu-6621]K-th Closest Distance 主席树 线段树 2019 多校4
    [POJ 2104]K-th Number 主席树 可持久化线段树 入门
    [hdu-6623]Minimal Power of Prime
    [hdu-6608] Fansblog 威尔逊定理 质数的密度分布 2019 多校 3
    [codeforces1000F] One Occurrence
    [python] 机器学习 卷积神经网络 用迁移学习实现人脸识别
    [python] 安装TensorFlow问题 解决Cannot uninstall 'wrapt'. It is a distutils installed project
    浅谈getResource方法
  • 原文地址:https://www.cnblogs.com/pangblog/p/3243713.html
Copyright © 2011-2022 走看看