zoukankan      html  css  js  c++  java
  • 内存管理-MRC与ARC详解

    Objective-C提供了两种内存管理机制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),为Objective-C提供了内存的手动和自动管理。下面我们来讲解MRC和ARC的基本概念以及自己的理解,欢迎大家指正!!!

    一、前言

    在讲述MRC和ARC之前,我们先来看一下Objective-C的引用计数式的内存管理方式。下面是一些特点:

    1. 自己生成的对象,自己持有。(通过alloc/new/copy/mutableCopy等方法)例如:NSObject *obj = [[NSObject alloc]init];
    2. 不是(非)自己生成的对象,自己也能持有:NSMutableArray *array = [NSMutableArray array];
    3. 无法释放非自己持有的对象

    1.自己生成的对象,自己持有

    在iOS内存管理中,有四个这样的关键字:new、alloc、copy、mutableCopy,如果自身使用这些关键字的时候来产生对象,那么创建完之后,自身也就有了对象。

        // 使用了alloc分配了内存,obj指向了对象,该对象本身引用计数为1,不需要retain 
        id obj = [[NSObject alloc] init]; 
        // 使用了new分配了内存,objc指向了对象,该对象本身引用计数为1,不需要retain 
        id obj = [NSObject new];

    2.非自己生成的对象,自己也能持有

        // NSMutableArray通过类方法array产生了对象(并没有使用alloc、new、copy、mutableCopt来产生对象),因此该对象不属于obj自身产生的
        // 因此,需要使用retain方法让对象计数器+1,从而obj可以持有该对象(尽管该对象不是他             产生的)
        id obj = [NSMutableArray array];
        [obj retain];     

    3.无法释放非自己持有的对象

     // 释放一个不属于自己的对象
        id obj = [NSMutableArray array]; 
         
     // obj没有进行retain操作而进行release操作,然后autoreleasePool也会对其进行一次release操作,导致奔溃。
      [obj release];

    针对[NSMutableArray array]方法取得对象方法,自己并不会持有对象,在底层是这样实现的

    + (id)object {
        //自己持有对象
        id obj = [[NSObject alloc]init];
         
        [obj autorelease];
         
        //取得的对象存在,但自己不持有对象
        return obj;
    }

    使用了autorelease方法,将obj对象注册到autoreleasePool中,不会立即释放,当pool结束时,再自动调用release。只有这样达到取得对象存在,而自己不持有对象。

    下面是来拓展一个问题:[className new]与[[className alloc] init]区别?

    面对区别,我么首先来看一下两个的源码。

    + new 
    { 
    id newObject = (*_alloc)((Class)self, 0); 
    Class metaClass = self->isa; 
    if (class_getVersion(metaClass) > 1) 
    return [newObject init]; 
    else 
    return newObject; 
    }
    
    
    
    //而 alloc/init 像这样: 
    + alloc 
    { 
    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());  
    } 
    - init 
    { 
    return self; 
    } 

    通过上面的源码,我们可以发现[className new]与[[className alloc] init]基本是等同的。

    区别也在于alloc 分配内存的时候使用了zone方法。zone方法是给对象 分配内存的时候,把要关联的对象分配到一个相邻的内存区域,这样调用消耗很少的代码,提高了程序的处理速度。

    大家发现,如果使用new的时候,初始化方法就会被固定住,只能调用init,如果要想调用initXXX方法怎么办,这样就不行了。

    总结:采用new的方式只能通过默认的init方法完成初始化;采用alloc的方式可以使用其他的定制方法。

    MRC

    retain:作用是将内存数据被指向的一个指针变量,引用计数retainCount + 1

    release:作用是引用计数减1,也即是retainCount -1,

    autorelease:作用是将内存的管理放到autoreleasepool中去

    其中retain和release操作的是引用计数,当引用计数为0时,便会自动释放内存。

    //如果Number为预定义的类

    Number *num = [Number alloc]init;

    Number *num2 =  [num retain];//此时引用记数+1,现为2

    [num2 release];//num2为-1,现为1

    如果再次调用[num2 release]引用计数为0

     ARC

    在我们项目中,打开ARC的方式与关闭ARC的方式如下:

    选择Targets -> Compile Phases -> Compile

    • 打开ARC:-fobjc-arc
    • 关闭ARC:-fno-objc-arc

    ARC的修饰符

    Objective-C的ARC提供了__weak,__strong,__autoreleasing和__unsafe_unretained。下面我们一起看一下:

    __weak

    代表的弱引用,对象在被释放的时候,指向它的弱引用会自动被置为nil。这样可以防止野指针的产生,__weak也被用于delegate关系中防止循环引用。

    __strong

    代表的是强引用,如果在声明引用的时候,不加入修饰符,那么默认是强引用。

    __autoreleasing

    代表在autorelease pool中自动释放对象的引用,和MRC中的autorelease用法是一样的。但是需要注意一点:定义的property时不能使用这个修饰符,因为任何一个对象的property都不会是autorelease型的。

    __unsafe_unretained

    主要是针对iOS 4,现在已经退出了,大家可以不要深入了解。

    以上就是ARC与MRC的基本内容,希望对大家有所帮助。

    下一步将讲述MRC-block以及ARC-block的区别,继续探讨ARC与MRC。

  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/9480518.html
Copyright © 2011-2022 走看看