zoukankan      html  css  js  c++  java
  • 手动内存

    为什么要内存管理?

    因为内存一直被占用的话,内存最终会不够用。

    内存管理好处,1G可以运行3G应用,只要使用时不超过1G,及时释放的话。

    一.oc中采用“引用计数”(retainCount)方式管理对象所占内存(内存有指针指向的概念)。

    1. alloc为对象分配内存。dealloc为对象释放所占内存,不能手动调用。
    2. 使用alloc、new对象时,并将其引用计数器设为1,并拥有对象所有权。
    3. copy制造一个副本,并将副本的引用计数设为1,对原有的引用计数不影响,并拥有副本对象所有权。
    4. retain使引用计数加1,并拥有对象所有权。release使引用计数减1,并放弃对象所有权。
    5. 当对象的retainCount为0时,系统自动调用dealloc释放对象内存;否则,分配内存将一直被占用。
    6. autorelrease向NSAutoreleasepool注册。

    二.

    1. 引用计数:计内存的使用次数(内存被用了多少次)
    2. 所有权对象分为:程序员和系统。谁retain,所有权归谁。  NSString *sonCar = [mamaCar retain];//儿子有所有权,此时retain引用计数+1了,使用完后销毁不会出现野指针  NSString *friendCar = sonCar;//朋友没有使引用计数加1,也就是说当引用计数为0,对象销毁的时候,会出现friendCar这个野指针
    3. 消息(方法)是有延迟的,系统回收可能存在延迟,因为系统回收是以轮询的方式。就像现实中的保洁工人收垃圾。
    4. 引用计数为0是打印不出来的,因为0代表没有该对象了,所以retain方法调用不出来,这时候系统只能打印出1。
    5. 原则使用后立即释放。

    三.属性中内存管理

    1. 原则:一个类中,如果这个类有属性声明retain或者copy的属性,那么我们需要在这个类的dealloc方法里释放一次。
    2. 属性内存管理分析图
    3. 属性的赋值方式:
    • 先初始化对象a
    • b.a = a;
    • [a release];

    四.便利构造器内存管理

    1. 通过使用autorelease延迟release来管理构造器的对象。return [对象 autorelease];或@autoreleasepool{}
    2. NSAutoreleasePool自动释放池:
    • 当创建的对象未来某个时候销毁时,可以使用对象的autorelease。
    • 对象将所有权管理交给最近的NSAutoreleasePool对象,并由其全权管理。栈式结构(UINavigationController和图形上下文)
    • 当池对象drain或release时,会逐一对池内对象发送release消息。
    • 能不使用,尽量不使用aoturelease。知道什么时候用完,直接release。
    • 任何OC对象只要调用autorelease方法,就会把该对象放到离自己最近的自动释放池中(栈顶的释放池)

    五.检测工具

    1. static Analyzer-Analysis Policy
    2. product-》profile-》leaks

    六.类中self点出来的属性。需要autorelease。dealloc中不用[_xxxx release]。

    相反:_xxxx = [[**  alloc]init];的属性在dealloc中[_xxxx release];。不用autorelease。


     Teacher.h

    @interface Teacher : NSObject
    -(void)onClass;
    @end

    Teacher.m

    #import "Teacher.h"
    
    @implementation Teacher
    -(void)onClass
    {
        NSLog(@"teacher is on class");
    }
    @end

    Student.h

    #import "Teacher.h"
    @interface Student : NSObject
    {
        Teacher *_teacher;
    }
    
    //@property(nonatomic,retain)Teacher *teacher;
    -(void)setTeacher:(Teacher *)aTeacher;
    -(Teacher *)teacher;
    @end

    Student.m

    #import "Student.h"
    
    @implementation Student
    
    //@synthesize teacher = _teacher;
    //retain中@synthesize默认手动写法
    -(void)setTeacher:(Teacher *)aTeacher
    {
        if (_teacher != aTeacher)//旧对象不等于新对象的时候-赋新值
        {
            [_teacher release];//_teacher释放?第一次_teacher是nil(对nil release没影响),但是如果后面还要把对象赋给_teacher的话,这里必须先释放(对上次传入的对象先进行释放并放弃所有权)
            _teacher = [aTeacher retain];//把所有权给_teacher。copy的话这里也改为[aTeacher retain]
            
        }
    }
    -(Teacher *)teacher
    {
        return _teacher;
    }
    
    
    
    -(Student *)init
    {
        self = [super init];
        if (self)
        {
            
        }
        return self;
    }
    
    //重写
    -(void)dealloc
    {
        [_teacher release];//属性中retain,这里也要release
        NSLog(@"我(%@)快要被释放了。。。。。",self);

      [super dealloc];//第一步必须做的,保留父类释放
    } @end

    AppDelegate.m

     /*
        Student *s = [[Student alloc]init];
        NSLog(@"reatinCount = %d",s.retainCount);
        
        [s retain];
        NSLog(@"reatinCount = %d",s.retainCount);
        
        [s release];
        NSLog(@"reatinCount = %d",s.retainCount);
        
        [s release];
        NSLog(@"reatinCount = %d",s.retainCount);
        */
        //属性的内存管理
        Teacher *t = [[Teacher alloc]init];
        Teacher *t2 = [[Teacher alloc]init];
    
        Student *stu = [[Student alloc]init];
        stu.teacher = t;
        stu.teacher = t2;
        
        
        [t release];
        [t2 release];
        
        //sleep(10);//让系统休眠10秒
        
        [stu.teacher onClass];
        [stu release];
    /*
        Student *s1 = [[Student alloc]init];
        Student *s2 = s1;
        NSLog(@"s2 = %d",s2.retainCount);
        [s2 retain];//2
        NSLog(@"s1 = %d",s1.retainCount);
        NSLog(@"s2 = %d",s2.retainCount);
        [s1 release];
        NSLog(@"s1 = %d",s1.retainCount);
        NSLog(@"s2 = %d",s2.retainCount);
    */

    属性与构造器手动内存写法

    AInstance.h

    #import <Foundation/Foundation.h>
    
    @interface AInstance : NSObject
    {
        NSString *_name;
        int _age;
        int _cityCode;
    }
    
    -(void)setName:(NSString *)aName;
    -(NSString *)name;
    
    -(void)setAge:(int)aAge;
    -(int)age;
    
    -(void)setCityCode:(int)aCityCode;
    -(int)cityCode;
    
    -(AInstance *)initWithName:(NSString *)aName
                 andAge:(int)aAge
            andCityCode:(int)aCityCode;
    
    +(AInstance *)aInstanceWithName:(NSString *)aName
                      andAge:(int)aAge
                 andCityCode:(int)aCityCode;
    
    @end

    AInstance.m

    #import "AInstance.h"
    @implementation AInstance
    -(void)setName:(NSString *)aName
    {
        if (_name != aName)
        {
            [_name release];
            _name = [aName retain];
        }
    }
    -(NSString *)name
    {
        return _name;
    }
    
    -(void)setAge:(int)aAge
    {
        _age = aAge;
    }
    -(int)age
    {
        return _age;
    }
    
    -(void)setCityCode:(int)aCityCode
    {
        _cityCode = aCityCode;
    }
    -(int)cityCode
    {
        return _cityCode;
    }
    
    -(AInstance *)initWithName:(NSString *)aName
                 andAge:(int)aAge
            andCityCode:(int)aCityCode
    {
        self = [super init];
        if (self)
        {
            _name = aName;
            _age = aAge;
            _cityCode = aCityCode;
        }
        return self;
    }
    
    +(AInstance *)aInstanceWithName:(NSString *)aName
                      andAge:(int)aAge
                 andCityCode:(int)aCityCode
    {
        AInstance *ainstance = [[AInstance alloc]initWithName:aName
                                                       andAge:aAge
                                                  andCityCode:aCityCode];
        return [ainstance autorelease];
    }
    
    
    - (void)dealloc
    {
        [_name release];
        
        [super dealloc];
    }
    @end

    AppDelegate.m

    AInstance *a = [[AInstance alloc ]initWithName:@"jobs"
                                               andAge:19
                                          andCityCode:20];
        NSLog(@"%@",a.name);
        [a release];  

    2.

    NSAutoreleasePool

    /*任何OC对象只要调用autorelease方法,就会把该对象放到离自己最近的自动释放池中(栈顶的释放池)*/
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
        for (int i = 0; i < 1000000; i++)
        {
            NSMutableString *str = [[NSMutableString  alloc]init];
            [str autorelease];
            if (i%1000 == 0)
            {
                [pool release];/*该程序每执行1000次,就把池子销毁,
                                也就是str在自动释放池累积的对象不会超过1000个*/
                
                pool = [[NSAutoreleasePool alloc]init];//同时新建一个池子
            }
        }
        [pool release];
  • 相关阅读:
    常用的十种排序
    [CSP-S模拟测试]:Weed(线段树)
    [CSP-S模拟测试]:Blue(贪心)
    $LaTeX$数学公式大全13
    $LaTeX$数学公式大全12
    $LaTeX$数学公式大全11
    $LaTeX$数学公式大全10
    $LaTeX$数学公式大全9
    $LaTeX$数学公式大全8
    [CSP-S模拟测试]:石头剪刀布(rps)(概率DP)
  • 原文地址:https://www.cnblogs.com/huen/p/3521276.html
Copyright © 2011-2022 走看看