深拷贝详解

第一、复制对象的基本概念

复制一个对象为副本,开辟一块新的内存来存储副本对象。

第二、如果一个对象想具备复制的功能,必须实现协议和协议

NSObject自带的常用的对象有:NSNumber、NSString、NSArray、NSDictionary、NSMutableArray、NSMutableDictionay、NSMutableString,copy产生的对象时不可变的,mutableCopy产生的对象时可变的

第三、retain和copy的区别

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@autoreleasepool {
     NSMutableArray *array=[NSMutableArray arrayWithObjects:@ "one" ,@ "two" ,@ "three" ,@ "four" ,nil];
     NSMutableArray *retainArray=[array retain];
     [retainArray removeLastObject];
     for (NSString *str in array)
     {
         NSLog(@ "the part is %@" ,str);
     }
     NSLog(@ "the retaincount is %ld" ,[retainArray retainCount]);
     // insert code here...
     NSLog(@ "Hello, World!" );
     
}

结果:

?
1
2
3
4
2014 - 05 - 19 10 : 58 : 22.639 objective[ 1095 : 303 ] the part is one
2014 - 05 - 19 10 : 58 : 22.641 objective[ 1095 : 303 ] the part is two
2014 - 05 - 19 10 : 58 : 22.641 objective[ 1095 : 303 ] the part is three
2014 - 05 - 19 10 : 58 : 22.641 objective[ 1095 : 303 ] the retaincount is 2
?
1
2
3
4
5
6
7
8
NSMutableArray *array=[NSMutableArray arrayWithObjects:@ "one" ,@ "two" ,@ "three" ,@ "four" ,nil];
         NSMutableArray *retainArray=[array mutableCopy];
         [retainArray removeLastObject];
         for (NSString *str in array)
         {
             NSLog(@ "the part is %@" ,str);
         }
         NSLog(@ "the retaincount is %ld" ,[retainArray retainCount]);


结果

2014-05-19 10:59:03.826 objective[1104:303] the part is one

2014-05-19 10:59:03.828 objective[1104:303] the part is two

2014-05-19 10:59:03.828 objective[1104:303] the part is three

2014-05-19 10:59:03.829 objective[1104:303] the part is four

2014-05-19 10:59:03.829 objective[1104:303] the retaincount is 1


第四、COPY和MutableCopy的区别

COPY 返回一个不可变对象的副本,MutalbeCopy返回一个可变对象的副本。

?
1
2
3
4
5
6
7
NSArray *array=[NSArray arrayWithObjects:@ "one" ,@ "two" , nil];
NSMutableArray *array1=[array copy];
[array1 addObject:@ "three" ];  //error
NSMutableArray *array2=[array mutableCopy];
[array2 addObject:@ "three" ];  //right
// insert code here...
NSLog(@ "Hello, World!" );

第五、浅copy和深copy

浅复制尽复制对象本身,对象里的属性、包含的对象不做复制

深复制复制全部,包括对象的属性和其他对象

Foundation框架支持复制的类,默认是浅复制

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSMutableArray *array=[[NSMutableArray alloc] init];
for ( int i= 0 ;i< 3 ;i++)
{
     NSObject *obj=[[NSObject alloc] init];
     [array addObject:obj];
     [obj release];
}
for (NSObject *obj1 in array)
{
     NSLog(@ "地址为 %p,引用计数是 %ld" ,obj1,obj1.retainCount);
}
NSMutableArray *array2=[array copy];
for (NSObject *obj2 in array2)
{
     NSLog(@ "地址为 %p,引用计数是 %ld" ,obj2,obj2.retainCount);
}

?
1
2
3
4
5
6
2013 - 09 - 30 17 : 28 : 01.492 FDAS[ 681 : 303 ] 地址为 0x1001081f0 ,引用计数是 1
2013 - 09 - 30 17 : 28 : 01.506 FDAS[ 681 : 303 ] 地址为 0x100108230 ,引用计数是 1
2013 - 09 - 30 17 : 28 : 01.506 FDAS[ 681 : 303 ] 地址为 0x100108240 ,引用计数是 1
2013 - 09 - 30 17 : 28 : 01.507 FDAS[ 681 : 303 ] 地址为 0x1001081f0 ,引用计数是 2
2013 - 09 - 30 17 : 28 : 01.507 FDAS[ 681 : 303 ] 地址为 0x100108230 ,引用计数是 2
2013 - 09 - 30 17 : 28 : 01.507 FDAS[ 681 : 303 ] 地址为 0x100108240 ,引用计数是 2

第五、对象的自定义拷贝

对象拥有复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone方法和mutableCopyWithZone方法

深拷贝和浅拷贝的区别就在于copyWithZone方法的实现,

浅拷贝代码如下:

?
1
2
3
4
5
6
7
8
# import <foundation foundation.h= "" >
 
@interface Person : NSObject<nscopying>
@property (nonatomic,retain)NSString *name;
@property (nonatomic,retain)NSString *age;
 
@end
</nscopying></foundation>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
# import "Person.h"
 
@implementation Person
 
- (id)copyWithZone:(NSZone *)zone
{
    //实现自定义浅拷贝
     Person *person=[[self class ] allocWithZone:zone];
     person.age=_age;
     person.name=_name;
     return person;
}
@end

main函数为:
?
1
2
3
4
5
6
7
8
9
@autoreleasepool {
     
     Person *person=[[Person alloc] init];
     person.name=@ "andy" ;
     person.age=@ "20" ;
     
     Person *person2=[person copy];
     NSLog(@ "person 地址为%p,person2地址为%p" ,person.name,person2.name);
}
输出结果为:
?
1
2013 - 09 - 30 17 : 48 : 41.007 FDAS[ 732 : 303 ] person 地址为 0x1000022c8 ,person2地址为 0x1000022c8

深拷贝代码如下:
?
1
2
3
4
5
6
7
8
- (id)copyWithZone:(NSZone *)zone
{
    //实现自定义浅拷贝
     Person *person=[[self class ] allocWithZone:zone];
     person.age=[_age copy];
     person.name=[_age copy];
     return person;
}

结果:

?
1
2013 - 09 - 30 17 : 55 : 13.603 FDAS[ 742 : 303 ] person 地址为 0x1000022c8 ,person2地址为 0x1000022e8

?
1
2
3
4
NSArray *arr=[NSArray arrayWithObjects:@ "one" ,@ "two" ,nil];
NSArray *arr2=[arr copy];
NSLog(@ "the dress of arr is %p the dress of arr2 is %p" ,arr,arr2);
NSLog(@ "the retainCount is %ld" ,arr.retainCount);

执行结果为:

2013-09-30 18:01:01.394 FDAS[787:303] the dress of arr is 0x100108320 the dress of arr2 is 0x100108320

2013-09-30 18:01:01.396 FDAS[787:303] the retainCount is 2


结果是一样的,是因为Foundation对于不可变复制对象而言,copy方法做了优化,相当于retain,故retaincount变成2.

相当于 在copyWithZone方法中:return [self retain];

第六、copy、mutableCopy和retain之间的关系

在Foundation对象中,copy是一个不可变的对象时,作用相当于retain

当使用mutableCopy时,不管源对象是否可变,副本是可变的,并且实现真正意义上的copy

当我们使用copy一个可变对象时,副本对象是不可变的。


关于深拷贝和浅拷贝:

第一、浅拷贝:

?
1
2
3
4
5
Car *car=[[[self class ] allocWithZone:zone] init];
car.engine=_engine;
car.name=_name;
car.weight=_weight;
return car;

测试代码:

?
1
2
3
4
5
6
7
8
9
10
11
Car *car = [[Car alloc] init];
        Engine *engine = [[Engine alloc] init];
        car.engine = engine;
        [engine release];
        //NSLog(@"engine retaincount is %lu",[engine retainCount]);
        car.name = @ "奥迪" ;
        car.weight = @1000 ;
 
        Car *car2=[car copy];
       // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);
        NSLog(@ "car %@,car2:%@" ,car.engine,car2.engine);

输出结果:

car ,car2:

可以看出浅复制只是复制指针,并没有创建新的内存空间

第二、深拷贝:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
- (id)copyWithZone:(NSZone *)zone {
     /***浅拷贝**/
     Car *car=[[[self class ] allocWithZone:zone] init];
     Engine *engineCopy=[[_engine copy] autorelease];
     car.engine=engineCopy;
     
     NSString *namecopy=[[_name copy] autorelease];
     car.name=namecopy;
     
     NSNumber *weightcopy=[[_weight copy] autorelease];
     car.weight=weightcopy;
     return car;
}

测试代码:
?
1
2
3
4
5
6
7
8
9
10
11
Car *car = [[Car alloc] init];
         Engine *engine = [[Engine alloc] init];
         car.engine = engine;
         [engine release];
         //NSLog(@"engine retaincount is %lu",[engine retainCount]);
         car.name = @ "奥迪" ;
         car.weight = @1000 ;
 
         Car *car2=[car copy];
        // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);
         NSLog(@ "car %@,car2:%@" ,car.engine,car2.engine);

结果:

car ,car2:

开辟了新的空间,zone代表一块内存空间
?
1
Car *car=[[[self class ] allocWithZone:zone] init];

注意上述代码用的是【self class】,而不是car,因为如果是用car,那么car的子类在调用此方法去实现copy协议时,就会出现内存问题

另外,当子类继承了父类时,他继承了父类的一切属性,包括要实现的协议

第三、NSFoundation,当我们copy的时一个不可变对象时,默认的copy都是浅拷贝,相当于retain

?
1
2
3
4
5
NSArray *array =[NSArray arrayWithObjects:@ "one" ,@ "two" ,@ "three" , nil];
NSArray *array1 = [array copy];
NSLog(@ "%p" ,array);
NSLog(@ "%p" ,array1);
NSLog(@ "the retaincount is %lu" ,[array retainCount]);

输出结果:

copyDemo1[673:303] 0x10010a5d0

2013-12-28 20:01:10.969 copyDemo1[673:303] 0x10010a5d0

2013-12-28 20:01:10.969 copyDemo1[673:303] the retaincount is 2

注意retaincount会增加

当使用mutableCopy时,不管对象是否可变,都会实现深拷贝

?
1
2
3
4
5
NSArray *array =[NSArray arrayWithObjects:@ "one" ,@ "two" ,@ "three" , nil];
NSMutableArray *array1 = [array mutableCopy];
NSLog(@ "%p" ,array);
NSLog(@ "%p" ,array1);
NSLog(@ "the retaincount is %lu" ,[array retainCount]);

结果:

copyDemo1[695:303] 0x10010a5d0

2013-12-28 20:07:08.570 copyDemo1[695:303] 0x10010b260

2013-12-28 20:07:08.570 copyDemo1[695:303] the retaincount is 1

第四、retain相当于两个对象指向同一个指针
?
1
2
3
4
5
NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@ "one" ,@ "two" ,@ "three" ,@ "foure" , nil];
NSMutableArray *array2 = [array1 retain];
[array2 removeLastObject];
NSLog(@ "%@" ,array1);
NSLog(@ "the retaincount is %ld" ,array2.retainCount);
结果:
?
1
2
3
4
5
6
2013 - 12 - 28 20 : 13 : 02.915 copyDemo1[ 736 : 303 ] (
     one,
     two,
     three
)
2013 - 12 - 28 20 : 13 : 02.917 copyDemo1[ 736 : 303 ] the retaincount is 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值