zoukankan      html  css  js  c++  java
  • 内存管理(Memory Management,retain, dealloc,new,copy,MRC)

    内存管理(Memory Management)

            内存管理的方式

            垃圾回收机制(gc, garbage collection), 油系统管理内存, 开发人员不需要关心内存, 系统会自动检测, 自动释放, 比如java

            : OC1.0不支持垃圾回收机制, 2.0时支持来及回收机制, 但是在iOS平台上苹果把OC的垃圾回收机制屏蔽掉了

            iOS不支持垃圾回收机制, 如何管理内存?

            通过引用计数(retain count)管理内存

            通过引入计数来管理内存, 有两种方式

            1.MRC, Manual Reference Count, 手动引用计数, 由开发人员通过引入计数来管理内存

           MRC设置

            2.ARC, Automatic Reference Count, 自动引入计数, 由系统通过引入计数来管理内存

            图中行为   OC操作                   OC方法

            开灯      开辟内存空间, 生成对象      alloc/new/copy

            需要照明   持有对象                  retain/copy

            不需要照明释放对象                  release/autorelease

            关灯      回收内存空间, 丢弃对象      dealloc

            : 需要照明的人数, 就是引入计数

            持有: 只要对这个对象做了引用计数+1的操作, 就叫人持有了这个对象

            alloc, 从堆区开辟内存空间

            引用计数: 0变成1

            自己创建的对象, 自己持有

            Light *light = [[Light alloc] init];
            NSLog(@"%lu", light.retainCount);

            retain, 引用计数+1

            持有某个对象

            [light retain];
            NSLog(@"%lu", light.retainCount);

    安全使用对象: 先持有, 再使用

            release, 引用计数-1

            不再使用某个对象时, 释放该对象

            [light release];
            NSLog(@"%lu", light.retainCount);  
            [light release];//light.retainCount = 0
    //        NSLog(@"%lu", light.retainCount);

     僵尸对象

            当对象的引入计数为0, 就不能再使用这个对象了, 如果再使用这个对象, 对象就会变成僵尸对象

            dealloc, 回收内存, 不允许手动调用, 当引用计数变成0时自动调用dealloc方法 

    Light.m
    #import "Light.h"
    @implementation Light
    - (void)dealloc
    {
        NSLog(@"关灯(回收内存)");
        [super dealloc];
    }
    @end

            new, 相当于alloc + init

            Light *light1 = [[Light alloc] init];
            Light *light2 = [Light new];
            NSLog(@"%lu, %lu", light1.retainCount, light2.retainCount);
            [light1 release];
            [light2 release];

    autorelease, 自动释放, 在未来的某段时间, 引用计数-1

            Light *light3 = [[Light alloc] init];
            [light3 autorelease];
            NSLog(@"%lu", light3.retainCount);

     : 对一个对象使用autorelease操作, 这个对象不回立刻引用计数-1, 而是先放到自动释放池中, 当自动释放池结束, 会对池中的对象依次做引用计数-1

     autoreleasepool只对调用了autorelease的对象起作用

     copy

    前提: 必须遵守<NSCopying>协议

            Light *lightA = [[Light alloc] init];       
            Light *lightB = [lightA copy];
            NSLog(@"%@", lightA);
            NSLog(@"%@", lightB);     
            [lightA release];
            [lightB release];

     浅拷贝: 拷贝指针, 内存地址空间一样

            lightB = [lightA retain];

    深拷贝: 拷贝内存空间, 内存地址空间不一样

    Light.m
    - (id)copyWithZone:(NSZone *)zone { //zone: 内存空间 //1.深拷贝 Light *light = [[Light allocWithZone:zone] init]; return light; //2.浅拷贝 // return [self retain]; }

    内存管理的原则

            1.引用计数+1的操作(alloc, new, copy, retain)的次数 = 引用计数-1的操作(release, autoreleasse)的次数

            2.对象的引用计数变为0就不能使用该对象

            3.谁创建谁释放想使用先持有

            4.当不使用某个对象时要及时释放

            只有堆区的内存需要管理其他由系统管理

            NSString *string = @"辉哥真帅!";
            NSLog(@"%lu", string.retainCount);
            [string release];
            NSLog(@"%lu", string.retainCount);
            [string retain];
            NSLog(@"%lu", string.retainCount);
            
            NSString *str = [[NSString alloc]initWithFormat:@"辉哥帅的无法形容O(∩_∩)O哈哈哈~"];
            NSLog(@"%lu", str.retainCount);
            [str release];

    NSString,创建字符串, 判断常量区内有没有, 如果有就返回常量区的字符串; 如果没有, 就从堆区开辟一块内存区域存放字符串

            NSString *str1 = [[NSString alloc] initWithFormat:@"1234567"];
            NSLog(@"%lu", str1.retainCount);
            [str1 release];
    Person.h
    #import <Foundation/Foundation.h>
    //姓名 性别 年龄
    //自定义初始化方法
    //便利构造器
    //重写description方法
    @interface Person : NSObject
    //属性的修饰词的默认值
    //atomic, assign, readwrite
    @property (nonatomic, retain) NSString *name;
    @property (nonatomic, copy) NSString *gender;
    @property (nonatomic, assign) NSInteger age;
    - (instancetype)initWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age;
    + (instancetype)personWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age;
    @end
    Person.m
    #import "Person.h"
    @implementation Person
    @synthesize age = _age, name = _name, gender = _gender;
    //修饰词是assign的setter和getter的实现
    - (void) setAge:(NSInteger)age {
        _age = age;
    }
    - (NSInteger)age {
        return _age;
    }
    - (void)dealloc
    {
        [_name release];
        [super dealloc];
    }
    //修饰词是retain的setter和getter的实现
    - (void)setName:(NSString *)name {
        if (_name != name) {//判断新对象的地址和原对象的地址是否一致, 如果一致, 就不需要改变; 如果不一致, 才需要改变
            [_name release];//释放原来对象, 拥有新对象
            _name = [name retain];//先持有, 才能安全使用
        }
    }
    - (NSString *)name {
        return  _name;
    }
    //修饰词是copy的setter和getter的实现
    - (void)setGender:(NSString *)gender {
        if (_gender != gender) {
            [_gender release];
            _gender = [gender copy];
        }
    }
    - (NSString *)gender {
        return _gender;
    }
    - (instancetype)initWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age {
        if (self = [super init]) {
            _name = name;
            _gender = gender;
            _age = age;
        }
        return  self;
    }
    + (instancetype)personWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age {
        return [[Person alloc] initWithName:name gender:gender age:age];
    }
    - (NSString *)description {
        return [NSString stringWithFormat:@"name:%@ gender:%@ age:%ld", _name, _gender, _age];
    }
    @end
            NSString *nameString = [[NSString alloc] initWithFormat:@"adasfdhgvjhk"];       
            Person *person = [[Person alloc] init];
            person.age = 18;
            person.name = nameString;
            [nameString release];       
            NSString *nameString1 = [[NSString alloc] initWithFormat:@"dfdfdfdf"];
            person.name = nameString1;
            [nameString1 release];        
            [person release];

    创建池子的两种写法

    写法1

        @autoreleasepool {
            Light *light4 = [[Light alloc] init];
            [light4 autorelease];
        }

    写法2

        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        Light *light5 = [[Light alloc] init];
        [light5 autorelease];
        [pool release];

     

     

    The one who wants to wear a crown must bear the weight!
  • 相关阅读:
    Insufficient parameters supplied to the command
    helloworld program of Linden Scripting Language
    使用DEV控件开发的小软件,单词查询及单词浏览
    SqlBulkCopy基本使用
    .NET3.0+中使软件发出声音[整理篇]
    Quick Hack for Setting the Row Height of a ListViewItem
    WCF返回JSON及EXT调用WCF
    拖动PictureBox 代码片断
    WCF配置工具及服务调试工具
    为指定的XML文件生成类并反序列化
  • 原文地址:https://www.cnblogs.com/OrangesChen/p/4872607.html
Copyright © 2011-2022 走看看