zoukankan      html  css  js  c++  java
  • [转载]关于内存管理,写一个简单易懂的教程

    此博客用于学习笔记,需要删除请联系我,原文链接 http://www.1000phone.net/thread-7617-1-1.html

    管理原则:

    谁用谁retain,谁retain的谁release。

    1 ClassA *obj1 = [[ClassA alloc] init]; 
    2 //这里你申请了一块内存地址,指针obj1指向了这块内存地址,同时你给它retain了一下(retain,copy,alloc这几个方法都相当于把retaincount加一),此时obj1所指向的这块内存地址retaincount为1。
    3 
    4 ClassA *obj2=obj1;
    5 [obj2 retain];
    6 //obj1和obj2同时都指向了上面所述的内存地址,我假设这块内存为A,那么A这块内存的retaincount为2。
    7 [obj1 release];
    8 [obj2 release];
    9 //最后不用的时候,需要释放了

    二、不要随便看到retaincount多就给它释放
    很多朋友在学完内存管理后喜欢玩消除,不该释放的他去释放,举个例子

    UIViewController *ct1=[[UIViewController alloc] init];
    [self.navigationcontroller pushViewController:ct1 animated:YES];
    [ct1 relese];

    这里,初始化一个viewcontroller,然后用导航push进来,最后释放这个viewcontroller,很多人在这里操作完毕后,继续打印ct1的retaincount,发现它的retaincount不为0,就继续release,这里是非常错误的方法,直接导致程序崩溃,继续看以上原则“谁用谁retain,谁retain的谁release”,你用的时候,初始化,并retain了一次,最后你release了一次,到此结束!之后不管你发现它的retaincount为几,你都不该再release。你打印出来的retaincount并不是你retain的,而是系统框架本身retain的,由框架本身来处理,开发者不必理会。
    类似还有很多,数组的addobject、addsubview等等很多方法,都是框架自己家retain的,开发者本身retain后release,不必理会它的retaincount。
    另外插一句,如果是多人协同开发,这种情况最容易碰到,别人传递一个参数过来,你拿过来retain后使用,使用完毕release,发现retaincount还不是0,于是你继续release,这样你就把你同伴retain的计数给release掉了,当他下次使用的时候发现崩溃了,这种情况会让你的团队浪费无数的时间来找原因。
    三、关于属性
    属性在.h文件中是这样声明的

    @property(nonatomic,retain) Class *obj;

    括号内第二个参数代表的意义是什么呢?
    我们分析一下他内部的机制
    @property (retain) Class* obj;@synthesize obj;实际上是gettersetter,有retain参数的property,内部代码如下

    -(Class *) getObj
    {
             return obj;
    }
    
    -(void) setObj:(Class *) value
    {
             if (obj != value)
             {
                       [obj release];
                       obj = [value retain];
             }
    }

    愿意仔细分析的童鞋可以仔细研究一下,不太明朗的童鞋请听我说。

    这个属性定义以后如何使用呢?我们只说赋值(也就是set)

    self.obj=xxx;
    [self setObj:xxx];
    obj=xxx;


    赋值方法有以下几种,其中前两个是相同的,都是调用了setObj:方法同时也就导致了obj的retaincount增加了1,而第三个赋值方法并没有增加retaincount,只是将指针指向了xxx内存地址。
    所以大家赋值时可以这样

    Class *c=[[Class alloc] init];
    self.obj=c;[c release];
    //或者 Class *c=[[Class alloc] init];
    [self setObj:c];[c release];
    //或者 Class *c=[[Class alloc] init];obj=c;

    属性的这个机制是让你在整个self里(也就是当前类的实例里)一直保留这个obj的retaincount,所以你必须在此类的dealloc里将obj的retaincount置零(你只需要release,如果你严格遵守“谁用谁retain,谁retain的谁release”的话)

    -(void)dealloc
    {
        [obj release];
        [super dealloc];
    }

    这里,其实我主要要说明的就是属性的赋值方式用self.xxx=xxxx和xxx=xxxx是完全不同的赋值方式,大家切记!
    四、autorelease对象
    autorelease对象就是自动释放对象,大家可能会疑惑,能自动释放,我还管理干嘛,我都用自动释放算了,事实不是这样的,自动释放确实好用,但是自己管理内存才能让项目占用更小的资源,跑起来更流畅,大家可以手动管理加autorelease一起来使用,我先讲解一下autorelease对象到底是什么个情况。
    首先,告诉大家autorelease对象什么时候才会被释放。
    在main函数里有一个autorelease pool,自动释放池,所以在这个自动释放池里的autorelease对象都会在自动释放池结束的时候全部被释放。
    大家可能会问了,“难道所有的autorelease对象都是在程序退出的时候才被释放?”,答案当然不是,其实main函数中只是一个程序中众多自动释放池中的一个,每个runloop都会隐性的创建一个自动释放池,啥是一个runloop?每个UIView创建、delegate回调等等都会创建一个自动释放池,记得这个“等等”,意思就是有很多(如果大家想要详细了解runloop,可以去google)。所以大家不用担心autorelease对象不会被释放。
    很多系统的方法,比如[NSArray array]、[NSString stringformat]等等返回的对象都是autorelease对象,这些对象是不需要手动释放的,如果手动释放会导致程序崩溃!切记!,原则就是系统中所有没有使用alloc、copy、retain来创建的对象都是autorelease对象,大家千万别手动release!


  • 相关阅读:
    刷题[极客大挑战 2019]HardSQL
    刷题[安洵杯 2019]不是文件上传
    归并排序算法及其JS实现
    快速排序算法原理及其js实现
    圣杯布局
    什么是文档流
    AngularJs四大特性
    call,apply,bind的区别
    计算给定数组 arr 中所有元素的总和的几种方法
    es6之Decorator
  • 原文地址:https://www.cnblogs.com/davidzhou11225/p/2550320.html
Copyright © 2011-2022 走看看