09 内存管理初级

⼀、内存管理的方式

1)简述

       1>ios应用程序出现Crash(闪退),90%以上的原因是内存问题,了解内存常见问题,帮助我们减少出错几率。内存问题体现在两个方面:内存溢出,野指针异常

       2>野指针异常:对象内存空间已经被系统回收,仍然使用指针操作这块内存野指针异常是程序crash的主要原因代码量越大的程序,越难找出现野指针的位置。 

野指针->最好安全释放

3>垃圾回收 (gc)        

程序员只需要开辟内存空间,不需要⽤代码显⽰地释,系统来判断哪些空间不再被使用,并回收这些内存空间,以便再次分配。整个回收的过程不需要写任何代码,由系统自动完成垃圾回收。Java开发中一直使用的就是垃圾回收技术

            MRC(Manual Reference Count)

人工引⽤计数:内存的开辟和释放都由程序代码进行控制。相对垃圾回收来说,对内存的控制更加灵活,可以在需要释放的时候及时释放,对程序员的要求较高,程序员要熟悉内存管理的机制。

    ARC (Auto Reference Count)

自动引用计数:iOS 5.0的编译器特性,它允许用户只开辟空间,不用去释放空间。它不是垃圾回收!它的本质 还是MRC,只是编译器帮程序员默认加了释放的代码。

⼆、引用计数机制,影响计数的各个方法

1)简述

C语⾔中,使⽤malloc和free,进⾏堆内存的创建和释放。堆内存只有正在使⽤和销毁两种状态。

OC采用引⽤计数机制管理内存,当一个新的引⽤指向对象时,引⽤计数器就递增,当去掉⼀个引⽤时,引⽤计数就递减。当引用计数到零时,该对象就将释放占有的资源。


+alloc :开辟内存空间,让被开辟的内存空间的引用计数变为1。 这是由0到1的过程

-retain :引用计数加1,如果内存空间之前引用计数为1,ratain之后变为2

-release :引⽤计数减1,如果内存空间之前引用计数为4,release之后变为3

-copy :把某一内存区域的内容拷贝一份,拷⻉到新的内存空间⾥去,被拷⻉区域的引用计数不变,新的内存区域的引⽤计数为1。

-autorelease:未来的某一时刻引用计数减1。如果内存之前引⽤计数为4,autorelease之后仍然为4,未来某个时刻会变为3。(延迟一段时间)

-autoreleasepool :向⼀个对象发送autorelease消息,这个对象何时释放,取决于 autoreleasepool

2)代码实例

// 1.创建Person对象

    // alloc将对象的引用计数器从01,从无到有

    Person *person1 = [[Person alloc]init]; // 计数器1

    // 改一下这里 Automatic Reference Counting 自动引用为 NO

    NSLog(@"%lu",[person1 retainCount]);

 

    // 2.使用新对象再持有一次

    // retain: 对象 的引用计数器 +1

    Person *person2 = [person1 retain]; //2

    NSLog(@"%lu",[person2 retainCount]);

    //不管有没有接收,只要给对象发送retain消息, 对象的引用计数器 +1

    [person1 retain]; //3

    NSLog(@"%lu",[person2 retainCount]);

    

    // 3. 将引用计数器 -1

    [person1 release];

    NSLog(@"%lu",[person2 retainCount]); //针对对象使用的,任何的对象都可以 //2

    [person1 release];

    NSLog(@"%lu",[person2 retainCount]);//1

    [person1 release], person1 = nil, person2 = nil; //person1 = nil,安全释放,指针置为nil

    NSLog(@"%lu",[person2 retainCount]);//1 内存已经被收回了


// 自动释放池

    NSAutoreleasePool *autoreleaselPool = [[NSAutoreleasePool alloc]init];

    Person *p1 = [[Person alloc]init];//1

    [p1 retain];//2

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

    //延迟释放

    [p1 autorelease];

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

    //销毁自动释放池

    [autoreleaselPool release];

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


//iOS5.0之后, 可以写 @autoreleasepool { }这种语法来表示自动释放

    @autoreleasepool {

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

        NSLog(@"%@",p2);

        [p2 autorelease];

        

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

        NSLog(@"%@",p3);

        [p3 autorelease];

    }




三、dealloc⽅法   对象死了属性消失

dealloc是继承自父类的方法,当对象引用计数为0的时候,由对象自动调用。

2)实例代码

- (void)dealloc

{

    NSLog(@"%@ 被释放了", self);

    // 使用从父类继承过来的方法,销毁从父类继承过来的属性或者实例变量

    [super dealloc];

}


四、内存管理的基本原则。 

凡是使⽤了allocretain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。

五、掌握copy的实现。   克隆  互不影响

一个对象想要copy,生成⾃己的副本,需要实现 NSCopying协议,定义copy的细节(如何copy)。如果类没有接受NSCopying协议而给对象发送copy消息,会引起crash。

Person.h文件中

//要想实现对象的拷贝,第一步是在文件.h中遵守<NSCopying>协议

@interface Person : NSObject<NSCopying>


@property (nonatomic , copy) NSString *name;

@property (nonatomic, assign) NSInteger age;


Person.m文件中

// 2实现<NSCopying>协议中的方法, copyWithZone:

- (id)copyWithZone:(NSZone *)zone

{

    // 创建一个和person一模一样的对象返回

    Person *p = [[Person allocWithZone:zone] init];

    p.name = self.name;

    p.age = self.age;

    return p;

    

}

        main,m 文件中

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

    p2.name = @"大丫头";

    p2.age = 19;

    Person *p = [p2 copy];

    NSLog(@"%@ %ld",p.name,p.age);





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值