zoukankan      html  css  js  c++  java
  • Objective

    在前面, 我们对OC的内存管理基本上有了一个认识, 也知道了多个对象的内存管理是如何处理, 虽然在前面的多对象内存管理符合内存管理的原则, 其实还有一定的小bug, 今天我们就来看看如何解决这个bug.


    例子:

    #import <Foundation/Foundation.h>
    #import "Car.h"
    @interface Person : NSObject
    {
        int _age;
        
        Car *_car;
    }
    
    - (void)setAge:(int)age;
    - (int)age;
    
    - (void)setCar:(Car *)car;
    - (Car *)car;
    
    @end
    
    @implementation Person
    - (void)setAge:(int)age
    {
        _age = age;
    }
    - (int)age
    {
        return _age;
    }
    
    - (void)setCar:(Car *)car
    {   
        _car = [car retain];
    }
    - (Car *)car
    {
        return _car;
    }
    
    - (void)dealloc
    {
        NSLog(@"%d岁的Person被释放.", _age);
        
        [super dealloc];
    }
    
    @end
    

    #import <Foundation/Foundation.h>
    
    @interface Car : NSObject
    {
        int _speed;
    }
    
    - (void)setSpeed:(int)speed;
    - (int)speed;
    @end
    
    @implementation Car
    - (void)setSpeed:(int)speed
    {
        _speed = speed;
    }
    - (int)speed
    {
        return _speed;
    }
    
    - (void)dealloc
    {
        NSLog(@"速度为%d的Car对象被回收了.", _speed);
        
        [super dealloc];
    }
    @end
    

    #import <Foundation/Foundation.h>
    #import "Car.h"
    #import "Person.h"
    
    int main(int argc, const char * argv[])
    {
        Car *c1 = [[Car alloc]init];
        
        c1.speed = 250;
        
        Person *p = [[Person alloc]init];
        
        p.age = 20;
    
        [p release];
        
        [c1 release];
        
        return 0;
    }
    

    这个例子和我们之前所看的多对象内存管理是一个原理, 有增有减, 一旦release之后, 所有对象都会被释放, 但如果改一下:

    int main(int argc, const char * argv[])
    {
        Car *c1 = [[Car alloc]init];
        
        c1.speed = 250;
        
        Person *p = [[Person alloc]init];
        
        p.age = 20;
        p.car = c1;
    
        [p release];
        
        [c1 release];
        
        return 0;
    }
    


    问题1. 经过了p.car = c1; 这句代码之后, 那么car的引用计数就是2, 打印的结果也就只有Person被释放.

    2015-01-26 14:38:43.066 2.set方法的内存管理[4557:447362] 20岁的Person被释放.
    



    问题2. 如果p这个对象有钱了, 需要换车:

    int main(int argc, const char * argv[])
    {
        Car *c1 = [[Car alloc]init];
        
        c1.speed = 250;
        
        Person *p = [[Person alloc]init];
        
        p.age = 20;
        p.car = c1;
        
        Car *c2 = [[Car alloc]init];
        c2.speed = 300;
        
        p.car = c2;
        
        [p release];
        
        [c1 release];
        
        return 0;
    }
    

    那么c1呢? c1并没有被释放, 看看下面的示意图:



    虽然在现实生活中是可以一个人拥有多部车, 但在OC中, 一旦你不用一个对象就必须的释放, 否则就会引起内存泄漏的问题.


    问题3. 一旦p这个对象换车了, 如果它不用新车, 也必须得对新车进行一次release, 否则也会引起内存泄漏.



    针对上面的三个问题, 其实我们可以添加两句代码解决, 比如:

    #import "Person.h"
    
    @implementation Person
    - (void)setAge:(int)age
    {
        _age = age;
    }
    - (int)age
    {
        return _age;
    }
    
    - (void)setCar:(Car *)car
    {
        [_car release]; //对当前正在使用的车(旧车)进行release.
    
        _car = [car retain];
    }
    - (Car *)car
    {
        return _car;
    }
    
    - (void)dealloc
    {
        // 当人被释放了, 那么车也要被释放
        [_car release];
        
        NSLog(@"%d岁的Person被释放.", _age);
        
        [super dealloc];
    }
    
    @end


    三个对象同时释放, 打印出来的结果:

    2015-01-26 14:57:42.084 2.set方法的内存管理[4688:455689] 20岁的Person被释放.
    2015-01-26 14:57:42.085 2.set方法的内存管理[4688:455689] 速度为250的Car对象被回收了.
    2015-01-26 14:57:42.085 2.set方法的内存管理[4688:455689] 速度为300的Car对象被回收了.
    


    但在这里还可以稍微进行一点优化, 免得以后引起一些不必要的问题:

    #import "Person.h"
    
    @implementation Person
    - (void)setAge:(int)age
    {
        _age = age;
    }
    - (int)age
    {
        return _age;
    }
    
    - (void)setCar:(Car *)car
    {
        if (car != _car)
        {
            [_car release]; //对当前正在使用的车(旧车)进行release.
            
            _car = [car retain]; // 对新车进行一次retain
        }
    
    }

    只有加上这个判断, 那么当你存入的对象如果和之前一样, 那么就不用做重复的操作, 不会引起不必要的问题, 比如:

    int main(int argc, const char * argv[])
    {
        Car *c1 = [[Car alloc]init];
        
        c1.speed = 250;
        
        Person *p = [[Person alloc]init];
        
        p.age = 20;
        p.car = c1;
        
        Car *c2 = [[Car alloc]init];
        c2.speed = 300;
        
        p.car = c2;
        
        [c1 release];
        p.car = c1;
        
        
        
        [p release];
    
        [c2 release];
        
        return 0;
    }
    



    好了, 这次我们就讲到这里, 下次我们继续~~

  • 相关阅读:
    earlycon 的使用【转】
    DDR工作原理【转】
    DDR工作时序与原理【转】
    kernel内存、地址【转】
    Linux时间子系统之定时事件层(Clock Events)【转】
    QEMU 2.10.1 编译安装【转】
    Kernel 内核调试【转】
    The Slab Allocator in the Linux kernel【转】
    Linux内存管理:slub分配器【转】
    linux内存管理笔记(二十七)----slub分配器概述【转】
  • 原文地址:https://www.cnblogs.com/iOSCain/p/4282826.html
Copyright © 2011-2022 走看看