内存管理 ARC + MRC

C语言内存管理

     char *p = malloc(100);   //在堆中开辟100个字节空间
        strcpy(p,"hello");
        NSLog(@"p = %s",p);

        fun1(p);

        fun2(p);

//C内存管理的隐患:

        //free(p);  //1.当fun1,fun2没用完malloc空间,执行了free,造成提前释放--野指针
        //2.担心传出去的空间,别人没用完,所有人都不去释放--内存泄漏
        free(p); //3.所有人都担心内存没释放,都执行free,造成重复释放 -- 奔溃

//OC中改善内存管理的机制--引用计数

        //引用计数: ARC 、MRC
        //ARC:  自动引用计数-(默认)
        //MRC:  手动引用计数## 标题 ##

ARC

int main(int argc, const char * argv[]) {
    @autoreleasepool { //自动释放池
        // insert code here...

        //ARC执行过程:
        //先执行@autoreleasepool括号内->dealloc->自动释放池括号外

        Person *per = [[Person alloc] init];
        NSLog(@"开辟空间");
    }
    NSLog(@"程序即将结束");
    return 0;
    }

//析构方法:释放内存的方法;程序执行完毕,进入dealloc,说明已经释放该对象

    - (void)dealloc
    {
        NSLog(@"Person dealloc");
    }

MRC

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        //MRC执行过程:
        //release:只要对象的引用计数为0->立即dealloc(不会等到自动释放池结束)(推荐)
        //autoRelease: 把引用计数-1抛给自动释放池,退出自动释放池立即执行dealloc
        Person *per = [[Person alloc] init];

        NSLog(@"开辟空间");
        [per release];  //引用计数-1;  减到0时,才释放(调用dealloc)

        //[per autorelease]; //有延迟的引用计数-1;
        NSLog(@"空间-1");
    }
    NSLog(@"应用程序执行结束");
    return 0;
    }

MRC的Retain调用

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

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

        Person *xiaoQ = [xiaoM retain];  //引用计数+1

        Person *xiaoB = [xiaoQ retain];

        NSLog(@"引用计数:%ld",[xiaoQ retainCount]);  //获取引用计数

        [xiaoM release];   //引用计数-1,计数还剩1

        NSLog(@"-1后,引用计数:%ld",[xiaoM retainCount]);  //获取引用计数

        //[xiaoM release]; err 一定要使用内存管理黄金法则
        [xiaoQ release];

        [xiaoB release];

        //释放的值,再打印无意义
        //NSLog(@"retainCount = %ld",[xiaoB retainCount]);

        //结论: 只要有alloc、retain、copy,就一定对应有release-内存管理黄金法则

    }
    return 0;
}

字符串的内存管理

    NSString *str = [[NSString alloc] init];

        //在字符串中不能用retainCount来获取引用计数
        NSLog(@"retainCount = %ld",[str retainCount]);   //-1


//1.NSString进行retain

        NSString *str1 = [str retain];  //引用计数+1

        //字符串通过打印地址的方式,验证引用计数是否+1
        NSLog(@"str1:%p,str: %p",str1,str);

        [str release];  //内部遵循内存管理的黄金法则
        [str1 release];


        NSMutableString *mutStr = [[NSMutableString alloc] init];

//2.NSMuatableString进行retain

        NSMutableString *mutStr1 = [mutStr retain]; //引用计数+1

        NSLog(@"mutStr:%p,mutStr1:%p",mutStr,mutStr1);

        //结论:可变与不可变字符串进行retain,引用计数都+1;

//3.NSString进行copy

        NSString *str2 = [str copy];   //引用计数+1

        NSLog(@"str: %p,str2: %p",str,str2);

//4.NSMuatableString进行copy

        NSString *str3 = [mutStr1 copy]; //引用计数不+1

        NSLog(@"str3 = %p,mutstr1=%p",str3,mutStr1);

        //结论:不可变进行copy引用计数+1,可变不+1;

//5.NSString进行mutableCopy

        NSMutableString *mutStr2=[str3 mutableCopy]; //引用计数不+1
        NSLog(@"mutStr2=%p,str3 = %p",mutStr2,str3);

//6.NSMutableString进行mutableCopy

        NSMutableString *mutStr3 = [mutStr2 mutableCopy];//引用计数不+1
        NSLog(@"mutstr3=%p,mutStr2=%p",mutStr3,mutStr2);

        //结论:可变与不可变字符串进行mutableCopy,引用计数都不+1;
//

        //深拷贝:引用计数不+1、字符串的mutableCopy始终为深拷贝
        //浅拷贝:引用计数+1、字符串的retain始终为浅拷贝

数组的内存管理

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


//1. 当元素对象放入数组,每一个对象的引用计数都+1

        NSMutableArray *mutArr = [[NSMutableArray alloc] initWithObjects:p1,p2,p3, nil];

        NSLog(@"p1 count = %ld",p1.retainCount);  //2
        NSLog(@"p2 count = %ld",p2.retainCount);  //2
        NSLog(@"p3 count = %ld",p3.retainCount);  //2

//2.在数组中添加一个对象,那么该对象的引用计数+1

        [mutArr addObject:p1];

        NSLog(@"p1 count = %ld",p1.retainCount);  //3
        NSLog(@"p2 count = %ld",p2.retainCount);  //2
        NSLog(@"p3 count = %ld",p3.retainCount);  //2

//3.数组中移除一个对象,那么该对象的引用计数-1

        [mutArr removeObject:p3];
        NSLog(@"p1 count = %ld",p1.retainCount);  //3
        NSLog(@"p2 count = %ld",p2.retainCount);  //2
        NSLog(@"p3 count = %ld",p3.retainCount);  //1

//4.数组中溢出所有对象,那么每一个对象的引用计数都-1

        [mutArr removeAllObjects];
        //[mutArr release];
        NSLog(@"p1 count = %ld",p1.retainCount);  //1
        NSLog(@"p2 count = %ld",p2.retainCount);  //1
        NSLog(@"p3 count = %ld",p3.retainCount);  //1


        [p1 release];  //引用计数为0,调用dealloc
        [p2 release];  //引用计数为0,调用dealloc
        [p3 release];  //引用计数为0,调用dealloc

总结

     //1.回顾C内存管理的缺陷
           //a. 提前释放  b. 重复释放  c. 没有释放
        //2.引用计数的概念:
           //a. ARC: 自动引用计数,退出自动释放池,系统自动会释放内存空间
           //b. MRC: 手动引用计数;
                //b1. 内存管理的黄金法则;
                //b2. MRC默认的调用方法及标准写法
                //调用方法:retain、retainCount、release、dealloc
                //标准写法:记住复合类内存管理,字符串在类中的内存管理
        //3. 字符串的内存管理
                //深拷贝与浅拷贝的概念
        //4. 数组的内存管理
                //记住4个结论
        //5.release与autorelease
            //release: 引用计数-1(MRC推荐使用)
            //autorelease: 有延时的引用计数-1

test

main:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        //创建对象
        Engine *eng = [[Engine alloc] init];
        Engine *eng2 = [[Engine alloc] init];

        Car *car1 = [[Car alloc] initWithEngine:eng];

        [car1 setEngine:eng2];

        //释放对象
        [eng2 release];
        [eng release];
        [car1 release];


    }
    return 0;
    }
car:

    @implementation Car

    //setter函数
    -(void)setEngine:(Engine *)engine
    {
    if (_engine != engine) {
        [_engine release];
        _engine = [engine retain];
    }
    }

    //getter函数
    -(Engine *)engine
    {
    return _engine;
    }

    //Car对象初始化
    -(id)initWithEngine:(Engine *)engine
    {
    self = [super init];
    if (self) {

     // _engine = [engine retain];
        _engine = engine;
        [engine retain];

    }
    return self;
    }

    //重写dealloc
    - (void)dealloc
    {
        [_engine release];
        NSLog(@"%@ was dealloc!",self);
        [super dealloc];
    }
    @end

Engine:

    @implementation Engine
    //重写dealloc
    - (void)dealloc
    {
        NSLog(@"%@ was dealloc!",self);
        [super dealloc];
    }
    @end
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值