OC 第四讲 内存管理机制,引用计数

来源:互联网 发布:知乎 如何提问 编辑:程序博客网 时间:2024/05/18 03:33

iOS 应用程序中会出现crash ,90%以上原因是内存问题。

了解内存问题并掌握内存管理的机制,就能减少出错几率,提高程序性能,大大减少调试时间。

常见内存问题:内存溢出,野指针异常。

首先,我们建立1个类:

import <Foundation/Foundation.h>

@interface Person : NSObject  <NSCopying>

{

NSString *_name;

}

///  初始化方法

- (id)initWithName:(NSString *)name;

/// 便利构造器

+ (id)personWithName:(NSString *)name;



实现部分:

#import "Person.h"

- (id)initWithName: (NSString *)name

{

self = [super init];

if (self) {

_name = name;

}

return self;

}


/// 便利构造器

+ (id)personWithName:(NSString *)name

{

    Person *p = [[[Person alloc] initWithName:name] autorelease]; //自动释放

    return p;

}


/// 实现协议copy的方法

- (id)copyWithZone:(NSZone *)zone

{

    Person *p = [[Person allocWithZone:zone]

                 initWithName:[NSString stringWithFormat:@"%@的克隆人", _name]];

    return p;

}


/// 重写父类的dealloc方法

- (void)dealloc      //验证对象引用计数是否为0

{

    

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

   //对成员变量释放

//    [_name release];

//    _name = nil;

    [super dealloc];

}



@end




main.m

        Person *jingGeGe = [[Person alloc] initWithName:@"靖哥哥"];//1  //开辟内存空间,引用计数由01

        NSLog(@"%p", &jingGeGe);                      //栈的地址

        NSLog(@"jingGeGe: %p", jingGeGe);             //堆的地址

        NSLog(@"%ld", [jingGeGe retainCount]);        //引用计数变为1

        

        Person *dongJing = [jingGeGe retain];//2      //主张对象持有权,引用计数累加1

        NSLog(@"%ld", [dongJing retainCount]);        //引用计数变为2

        NSLog(@"dongJing: %p", dongJing);

        

        [dongJing release];                           //释放对象,不再持有,引用计数未来减一

        NSLog(@"%ld", [jingGeGe retainCount]);        //引用计数变为1

        NSLog(@"%ld", [dongJing retainCount]);        //不是内存被回收,还可以用

        dongJing = nil;        //对象为空

        [dongJing release];    //[nil release]向一个空对象发送任何消息,不会产生任何效果,不会报错,不会crash

        NSLog(@"%ld", [dongJing retainCount]);        //对象赋予nil时,计数输出为0

        

        [jingGeGe release];                           //引用计数变为0;全部被回收

        NSLog(@"%ld", [jingGeGe retainCount]);        //输出计数还是1

//        [jingGeGe release];                         //野指针,crash

/*

  野指针异常主要成因:
  一、指针变量没有被初始化
  二、对象的内存空间已经被回收,仍然使用指针操作这块内存

*/

    

        //  (自动释放)autorelease的好处与习惯用法

        Person *laoWang = [[Person alloc] initWithName:@"隔壁老王"];       //1

//        [laoWang retain];                              //2,引用计数加1,变为2.不写就会被销毁!写了还剩1.

        [laoWang autorelease];

        NSLog(@"%ld", [laoWang retainCount]);          //2



OC采用引用计数(retain count)记录某块内存持有者的个数。当对象的内存多了一个持有者,引用计数器就递增,少了一个所有者,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

+ alloc //开辟内存空间,引用计数由0变1;

-  retain //主张对象持有权,引用计数累加1;

- release //释放对象,不再持有,引用计数减1;

- autorelease // 自动释放对象,引用计数未来减1;

- copy // 拷贝创建一个对象,原有对象引用计数不变。



内存管理原则:

You own any object youcreate by allocating memory for it or copying it.Related methods:alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:

If you are not the creator of an object, but want to ensure it stays in memory for you to use, you can express anownership interest in it. Related method:retain

If you own an object, either by creating it or expressing an ownership interest, you are responsible forreleasing it when you no longer need it.Related methods:release,autorelease

Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.


0 0