Sian 发表于 2014-3-18 23:53:19

内存管理关于set方法的一个典型示例

本帖最后由 Sian 于 2014-3-18 23:57 编辑

1、基本场景:对象的成员变量中包含另外的对象;
2、成员变量在赋值时便牵涉到内存管理的细节;
3、对象本身是内存释放时,需要对成员变量进行全部释放;

比如创建一个Person对象,Person对象中有成员变量Car(对象),通过几张图片来说明问题:
1、创建一个Person对象p



2、创建一个Car对象c1,_speed = 200



3、让p拥有c1对象(),此时c1的拥有者有两个,所以p在拥有c1时,需要进行一次retain操作(_car = ),此时c1的retainCount=2



4、再创建一个Car对象c2,为p拥有c2做准备,注意此时各对象的retainCount值



5、对象p想拥有c2,最直观的做法是直接将c2赋值给p的成员变量_car,但这里有一个很关键性的问题,p之前拥有了c1,并且对c1进行了retain操作,现在如果放弃c1,需要对c1进行release操作(),同时在重新拥有c2时,对c2进行retain操作(_car = ),所以p在重新拥有c2时,注意各对象的retainCount值



6、Car对象c1、c2都为临时对象,创建的目的都是为了为Person对象p服务,所以c1、c2创建好对象完成使命后,不应该再对创建好的Car对象一直拥有操作权,及时释放自身,所以c1与c2在完成赋值后进行release操作 ,之后c1的retainCount=0,对象被dealloc,c2的retainCount=1,此时只有一个拥有者,即p的成员变量_car



7、最后,如果Person对象p自身需要释放时,一定要及时对自己所拥有的对象进行释放,即p在进行release操作时,要对当前拥有的所有对象进行release操作,由于对象被释放时会调用dealloc方法,所以一般在对象的dealloc方法中对所拥有的成员变量对象进行release操作,保证Person对象释放后,他所拥有的对象都同时被释放;

参考代码如下:

Person.h
//
//Person.h
//Retain
//
//Created by yusian on 14-3-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Car.h"

@interface Person : NSObject
{

    Car * _car;
   
}

- (void)setCar:(Car *)car;
- (Car *)car;

@end


Person.m
//
//Person.m
//Retain
//
//Created by yusian on 14-3-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "Person.h"

@implementation Person

- (void)setCar:(Car *)car
{
    ;
    _car = ;
}
- (Car *)car
{
    return _car;
}

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

@end


Car.h
//
//Car.h
//Retain
//
//Created by yusian on 14-3-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Car : NSObject
{
    int _speed;
}
@property int speed;
@end


Car.m
//
//Car.m
//Retain
//
//Created by yusian on 14-3-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "Car.h"

@implementation Car

- (void)dealloc
{
    NSLog(@"The Car of speed=%d is dealloc...", _speed);
    ;
}

@end


main.m
//
//main.m
//Retain
//
//Created by yusian on 14-3-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"

int main()
{
    Person * p = [ init];
   
    Car * c1 = [ init];
    c1.speed = 200;
   
    Car * c2 = [ init];
    c2.speed = 300;

    ;
    ;
   
    ;
    ;
    ;

    return 0;
}
运行结果:
2014-03-18 23:51:22.626 Retain The Car of speed=200 is dealloc...2014-03-18 23:51:22.627 Retain The Car of speed=300 is dealloc...2014-03-18 23:51:22.628 Retain Person is dealloc...Program ended with exit code: 0
过程图pptx下载:**** Hidden Message *****


Sian 发表于 2014-3-19 07:52:56

为严谨起见,setCar:方法还需要进行改进:
- (void)setCar:(Car *)car
{
    if (car != _car) {
    ;
    _car = ;
    }
}
这样做的目的是为了防止;反复赋值c1把Car对象传递给_car后,c1自身会释放,此时只有_car对Car有拥有权,即此时Car对象的retainCount=1,如果再进行一次操作,会先进行(此时由于retainCount=0,对象被释放),再进行对象已不存在。
因此,如果同一对象反复赋值,应该直接忽略,不进行任何操作,即在方法里面加判断 if ( car != _car ) 才进行相关操作,否则不执行任何动作。
页: [1]
查看完整版本: 内存管理关于set方法的一个典型示例