内存管理Memory OC——第九天

1、   内存管理方式

        垃圾回收机制:(Garbage Collection),有系统管理内存,开发人员需要管理

        注:OC从2.0之后就开始支持垃圾回收机制,但是只适用于OS开发,(苹果电脑的操作系统),我们iOS平台是不支持垃圾回收机制;(面试题) 不支持垃圾回收机制,OC是如何管理内存的呢?

        //内存不释放 就叫内存泄露

//OC通过引入计数器管理内存


图中那个的行为

    OC中操作

OC中方法

根据照明设备所做的动作

对对象的操作

开灯  

生成对象

alloc/copy/new

需要照明

持有对象

return

不需要照明

释放对象

release/autorelese(不会立即释放且与@autoreleasepool配合使用)

关灯

废弃对象  

dealloc

        //图中需要照明的人数,就代表引用计数
        //1.当第一人"需要照明",引用计数+1     有0-->1
        //2.当第二个人"需要照明",引用计数+1     有1-->2
        //3.当第二个人"需要照明",引用计数+1     有2-->3
        //4.当有一个人"不需要照明",引用计数-1     有3-->2
        //5.当再有一个人"不需要照明",引用计数-1     有2-->1

        //6.当再有一个人"不需要照明",引用计数-1     有1-->0

2、iOS平台下适用计数器如何管理内存,有两种方式

     1.MRC:(Manual Reference Counting),手动引入计数器,有开发人员通过手动引入计数器来管理内存。

      2.ARC:(Automatic Reference Counting),自动引入计数器,由系统通过引入计数器管理内存

        //学习好MRC是为了更好使用ARC,iOS5.0之后就有了ARC;

ARC和MRC的混编

        1.如果工程环境是ARC,而部分文件使用了MRC,使用一个参数    -fno-objc-arc

        2.如果工程环境是MRC,而部分文件使用了ARC,使用一个参数     -fobjc-arc

==============================================================

例子: 1.自己创建的对象自己持有;

Person.h

@interface Person : NSObject

//名字的属性

@property (nonatomic,copy)NSString *name;

@end

Person.m

@implementation Person
//dealloc 方法是对象被销毁的时候自动调用的方法,不需要手动调用,由于dealloc方法是重写的父类,所以重写此方法的时候,一定要把父类的方法内容也写上

- (void)dealloc 

 {   NSLog(@"Person%@对象被销毁了",_name);
    //以后重写dealloc方法时一定调用[super dealloc];  且此方法一定要写在最下面

    [super dealloc];

}

@end

main.m

Person *p = [[Person alloc]init];//alloc会造成对象的引用计数器由0-->1

        p.name = @"缓缓";

        //如何判断一个对象是否被持有,就看它的引用计数
        //retainCount :对象的引用计数

        NSLog(@"%lu",p.retainCount); //计数器为1

        //如果自己创建的对象不使用时,释放对象,使用release
        [p release];
//     NSLog(@"%lu",p.retainCount);       对象死了就不能再使用它了

//     [p release];    不要过度释放,也等于操作僵尸对象

 Person *p2 = [[Person alloc]init];   //0--->1

        p2.name = @"武媚娘";

3、retain可以让对象的引用计数 +1
        //非自己创建的对象,自己也能持有
         p2 =  [p2 retain]; //由1--->2
        NSLog(@"%lu",p2.retainCount);
       
         //非自己创建的对象,自己也能持有
        Person *p3 = [p2 retain];
        NSLog(@"%lu",p3.retainCount);  //2--->3
        [p2 release];//3-->2
        [p2 release];//2-->1
        [p3 release];//1-->0
       
        Person *p4 = [[Person alloc]init];
        p4.name = @"小骨";
        [p4 retain];//2
        [p4 retain];//3
        [p4 retain];//4
        [p4 release];//3
        [p4 release];//2
        [p4 release];//1

        [p4 release];//0

//      [p4 retain];//人死不能复生,对象死也不能复生

4、 方法的基本使用

        1.retain : 计算器 +1   ,会返回对象本身;(返回值为id泛类型)

        2.release : 计数器 - 1,没有返回值

        3.retainCount 的作用:获取当前对象的计数器数值

        4.dealloc 当一个对象被销毁的时候,系统会自动调用,再次方法中一定要调用[super delloc];且这句话要放到最后;

5、 概念

    //僵尸对象:所占内存被回收的对象,就叫僵尸对象,僵尸对象不能再使用

        //野指针:指僵尸对象的指针就叫野指针

        //空指针:没有志向任何东西的指针就叫空指针叫空指针,(nil,NULL,0),给空指针发送消息
        //   alloc 对应  dealloc

        //  retain  对应 release

        区别: [[Person alloc]init];   内存永远不会被释放

        //        [[[Person alloc]init]release];  创建的同时立即就被释放掉

        //autorelease 相比 release,也能造成引用计数器-1,不过autorelease 不是立即-1,会在未来某段时间做-1操作;

6、 autorelease 执行实质,对一个对象使用autorelease 操作,这个对象的引用计数器不会立即减1,如果把这个autorelease  操作放到自动释放出中,会在出池子的一瞬间减1,如果你没有放到池子中,不会对autorelease  操作对象进行减1;

 注意:你要使用autorelease 必须和自动释放池配合使用

//        Person *p5 = [[Person alloc]init];//0--->1

//        p5.name = @"杀阡陌";

//        [p5 autorelease];//1

//        NSLog(@"%lu",p5.retainCount);

=======================================================

7、创建自动释放池的两种形式
        //第一种形式

//    NSAutoreleasePool  自动释放池类

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
        Person *p6 = [[Person alloc]init];
        p6.name = @"白子画";
        [p6 autorelease];//或者用[p6 release];
        NSLog(@"%lu",p6.retainCount);
        [pool release];
       
        //第二种形式
        @autoreleasepool {
            Person *p7 = [[Person alloc]init];
            p7.name = @"糖宝";
            [p7 autorelease];//未来的时间减1,出自动释放池减1
//            [p7 release];//-1     //过度释放
            NSLog(@"%lu",p7.retainCount);

    }//此时也会引起过度释放,是由autorelease引起的

8、 内存管理的原则
        //水污染谁治理,谁alloc谁release,谁return谁release,autorelease
        //你想占用某个对象,就应该让对象的计数+1,(也就是让对象做以retain操作)

        //当你不想持有(占有)某个对象时,就应该让对象的引用计数-1,(也就是让对象做一release操作)

重复使用的释放可以设置带有参数的宏定义,减少繁琐的程序

#define kRelease_Safe(_point) [_point release];_point = nil;

        Person *p8 = [[Person alloc]init];

        p8.name = @"紫熏";

        Person *p9 = [p8 retain];

        kRelease_Safe(p8);

        NSLog(@"%@",p9.name);

        kRelease_Safe(p9); 

//        [p8 release];//对一个空指针发送消息,没有任何影响

9、 NSMutableArray *mArray = [[NSMutableArray alloc]initWithCapacity:0];
        //向数组中添加十个人
        for (int i = 0; i < 10 ; i ++) {
                Person *person = [[Person alloc]init];
                person.name = [NSString  stringWithFormat:@"%d",i];
                //数组在添加元素的时候,会对添加的元素做一次retain操作
                [mArray addObject:person];
                kRelease_Safe(person);

        }

        NSLog(@"%@",mArray);
        //数组在释放自己之前,会对之前添加到数组中的元素进行引用计数减1的操作

        kRelease_Safe(mArray);

        //此时我们没有alloc 也没有retain ,所以不需要对数组mArray2 的内存释放负责
        NSMutableArray *mArray2 = [NSMutableArray array];//
        Person *p10 = [[Person alloc]init];
        p10.name = @"朱然";
        [mArray2 addObject:p10];

        kRelease_Safe(p10);

        NSString *string = [[NSString alloc]initWithString:@"12345678912345"];

        NSLog(@"%ld",string.retainCount);

 总结:非重点,但是考试一般会问及: 当使用stringWithFormat:创建的字符串对象当长度小于10的时候,在常量区;大于等于10的时候,在堆区;
          //使用其他方法创建的字符串都在常量区
        NSString *string2 = [NSString stringWithFormat:@"1234567890"];

        NSLog(@"%lu",string2.retainCount);

        //没人去释放字符串,stringWithFormat:  计数器1,其他计数为-1;

======================================================

10、 copy 对象能够使用copy操作的前提是,此类必须遵循NSCopying 协议

        //浅拷贝,只拷贝地址,同时对象的引用计数+1;此时拷贝出来的对象原对象的所占的空间大小相等,内容也相等

        //深拷贝 不止拷贝空间和内容,而且从新开辟了一块内存

区别:浅拷贝会造成原对象的引用计数加+1,而深拷贝不会造成原对象的计数加+1;    

例子:在Person类基础上举例

Person.h

#import

@interface Person : NSObject<</span>NSCopying>必须遵循NSCopying 协议

//名字的属性

@property (nonatomic,copy)NSString *name;

@end

Person.m

- (void)dealloc{  

NSLog(@"Person%@对象被销毁了",_name);

    [super dealloc];

}

- (id)copyWithZone:(NSZone *)zone{
    //返回对象的时候要做一次retain操作,外界的接受者才持有这个对象

    // return [self retain];

//深拷贝  返回的是新的对象,此时两个对象所占的空间大小相同,内容也相同
    Person *p = [[Person allocWithZone:zone]init];

    p.name = self.name;

    return p;

}

@end

main.m

  Person *p11 = [[Person alloc]init];
        p11.name = @"笙萧默";
        Person *p12 = [p11 copy];
        NSLog(@"%@",p12.name);

        NSLog(@"p11 = %p p12 = %p ",p11,p12);

     

        kRelease_Safe(p11);

        kRelease_Safe(p12);

=====================================================

11、 new  申请创建对象的同时让其引用计数0-—>1(不常用)

        //new其实就做了alloc和init 两步操作,申请空间并初始化
        //      [Person new] = [Person alloc]init];
        Person *p13 = [Person new];
        p13.name = @"东方";

        kRelease_Safe(p13);

总结:内存管理的总结

         1.引用计数+1(alloc ,copy , new , retain)
         2.引用计数 -1 (release , autorelease)
         3.要想内存不出现泄漏,引用计数-1的次数相等
         4.一旦引用计数为0的时候系统会自动调用dealloc 方法

         5.谁污染谁治理,谁alloc谁release,谁return谁release,autorelease

深入了解学习:http://blog.sina.com.cn/s/blog_814ecfa90102vuqv.html

欢迎学习本文,未经许可,不得私自转载!

时间: 2024-10-06 10:32:33

内存管理Memory&nbsp;OC——第九天的相关文章

内存管理Memory&amp;amp;nbsp;OC——第九天

1.   内存管理方式        垃圾回收机制:(Garbage Collection),有系统管理内存,开发人员需要管理        注:OC从2.0之后就开始支持垃圾回收机制,但是只适用于OS开发,(苹果电脑的操作系统),我们iOS平台是不支持垃圾回收机制:(面试题) 不支持垃圾回收机制,OC是如何管理内存的呢?        //内存不释放 就叫内存泄露 //OC通过引入计数器管理内存 图中那个的行为     OC中操作 OC中方法 根据照明设备所做的动作 对对象的操作 开灯   生

C++中的内存管理

在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存泄露.所以我们要学会内存管理,不要内存泄露.在C++中的内存管理机制和OC中的还不太一样,在OC中的ARC机制会给程序员的内存管理省不少事,但在C++中没有ARC所以我们要自己管理好自己开辟的内存.Java中也有自己相应的内存管理机制,比如JDBC里的获取的各种资源在finally里进行close等

Open Cascade中的内存管理

Open Cascade中的内存管理 Memory Management in Open Cascade eryar@163.com 一.C++中的内存管理 Memory Management in C++ 1. 引言 为了表现出多态,在C++中就会用到大量的指针和引用.指针所指的对象是从内存空间中借来的,当然要及时归还.特别是指针在程序中随心所欲地创建,因此,一个指针究竟指向哪个对象,一个对象到底被几个指针所指向,是程序员十分关注的事情. C++中涉及到的内存管理问题可以归结为两方面:正确地掌

OC内存管理

一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对

浅谈OC内存管理

一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对

OC内存管理-OC笔记

内存管理细节:http://blog.sina.com.cn/s/blog_814ecfa90102vus2.html 学习目标 1.[理解]内存管理 2.[掌握]第一个MRC程序 3.[掌握]内存管理的原则 4.[理解]野指针与僵尸对象 5.[理解]单个对象的内存管理 6.[理解]多个对象的内存管理 7.[掌握]set方法的内存管理 8.[掌握]@property参数 9.[掌握]@class关键字 10.[理解]循环retain 一.内存管理 程序在运行过程中会在堆空间创建大量的对象,当对象

【OC语法快览】四、基础内存管理

Basic Memory Management                                                           基础内存管理 If you're writing an application for Mac OS X, you have the option to enable garbage collection. In general, this means that you don't have to think about memory

linux0.11内核源码剖析:第一篇 内存管理、memory.c【转】

转自:http://www.cnblogs.com/v-July-v/archive/2011/01/06/1983695.html linux0.11内核源码剖析第一篇:memory.c   July  二零一一年一月六日 ----------------------------------------- 博主声明:1.本系列非linux系统教程,仅仅是针对linux0.11内核源码,所做的剖析,注释.2.本系列参考:深入理解linux内核.linux内核完全注释,linux内核源代码情景分析

iOS - OC 内存管理

1.OC 基本内存管理模型 1.1 自动垃圾收集 在 OC 2.0 中,有一种称为垃圾收集的内存管理形式.通过垃圾收集,系统能够自动监测对象是否拥有其他的对象,当程序执行需要空间的时候,不再被引用的对象会自动释放.iOS 运行环境并不支持垃圾收集,在这个平台开发程序时并没有这方面的选项.在 OS X 10.8 中垃圾收集已不再推荐使用. 1.2 自动释放池 自动释放池(autoreleasepool)的机制是它使得应用在创建新对象时,系统能够有效的管理应用所使用的内存.自动释放池可以追踪需要延时