Object-C的浅拷贝与深拷贝区别

1、要了解浅拷贝与深拷贝,首要的是理解浅拷贝是什么深拷贝是什么

<1>浅拷贝:就相当于retain,只copy了一个对象的引用,和本身是同一个对象,就相当于影子。

<2>深拷贝:从新开辟了一块内存空间,用来存放原来对象里面的东西,这个时候,copy出来的对象和原来的对象不是同一个对象,他们的内容一样,就相当于克隆人。

<3>拷贝出来的的对象是什么类型取决于使用什么拷贝。

 

2、拷贝的用法

<1>不可变copy拷贝不可变对象(浅拷贝):

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array1=[array copy];
NSLog(@"array1=%@",array1);
NSLog(@"array=%p,array1=%p",array,array1);
NSLog(@"array = %lu ,array1 = %lu",[array retainCount],[array1 retainCount]);

 

其输出结果:

看输出结果反馈出:对不可变数组array进行不可变copy时,拷贝出来的array1是跟array一样的对象且两个数组的引用计数都+1,相当于对array本身的一个引用而已。

 

 

<2>不可变copy拷贝可变对象(深拷贝):

NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array=[mArray copy];
NSLog(@"mArray=%p,array=%p",mArray,array);
NSLog(@"array=%@",array);
NSLog(@"array的类型%@",[array class]);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对可变数组mArray进行不可变copy操作,拷贝出来的array数组与mArray数组的内存地址是不一样的且两块内存地址内容是相同的,而内容是一样的且引用计数不发生改变,array数组的类型不变依旧是不可变数组。由此可以得出不可变copy拷贝可变对象是深拷贝。

 

 

<3>可变copy拷贝不可变对象(深拷贝):

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSMutableArray *mArray=[array mutableCopy];
NSLog(@"-%@",[[array mutableCopy] class]);
NSLog(@"array=%p,mArray=%p",array,mArray);
NSLog(@"mArray=%@",mArray);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对不可变数组array进行可变可变copy操作,拷贝出来的mArray数组与array数组的内存地址不同且两块内存地址内容是相同的,且拷贝出来的对象是可变的,引用计数并没有发生改变,由此可以得出可变copy拷贝不可变对象是深拷贝。

 

 

<4>可变copy拷贝可变对象(深拷贝):

 NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
 NSMutableArray *array=[mArray mutableCopy];
 NSLog(@"%@",[[mArray mutableCopy] class]);
 NSLog(@"mArray=%p,array=%p",mArray,array);
 NSLog(@"array=%@",array);
 NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对可变数组array进行可变可变copy操作,拷贝出来的array数组与mArray数组的内存地址不同且两块内存地址内容是相同的,且拷贝出来的对象是可变的,没有引起引用计数的变化,由此可以得出可变copy拷贝可变对象是深拷贝。

 

 

<5>自定义类的copy:

自定义一个person类

.h文件

#import <Foundation/Foundation.h>
//要实现copy必须遵守NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone:
@interface Person : NSObject<NSCopying>
@property(retain,nonatomic)NSString *name;

@property(copy,nonatomic)NSArray *array;
@property(copy,nonatomic)NSMutableArray *mArray;

@end

 

.m文件

#import "Person.h"

@implementation Person
-(id)copyWithZone:(NSZone *)zone
{
    Person *pp=[[Person alloc]init];
//    NSLog(@"pp=%p",pp);
    pp.name=self.name;
    return pp;
}
@end

 

在main.m文件中,导入person类头文件且添加下列代码

/*
     要实现copy必须遵守NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone:
*/

    Person *p=[[Person alloc]init];
    p.name=@"张三";
    Person *p1=[p copy];
    NSLog(@"p=%p,p1=%p",p,p1);
    NSLog(@"p1的名字为%@",p1.name);

运行结果得到:

可以得出:自定义对象进行copy操作得到的是两块补一样的内存地址,且内容是一样的。

 

 

<6>属性的copy:

    1copy修饰不可变属性的时候,就相当于retain

    2copy修饰可变属性的时候,相当于不可变copy拷贝可变对象。属于深拷贝,这个时候,属性和对属性赋值的对象的内存都需要单独管理

    3、建议对象类型都是用retain

 

posted @ 2016-01-19 11:36  顶级蜗牛的技术博客  阅读(640)  评论(1编辑  收藏  举报