android深浅拷贝,iOS中的深复制与浅复制

多语言中都有深复制浅复制的概念,如C++,ObjC等。简单来说,浅复制就是两个变量指向了同一块内存区域,深复制就是两个变量指向了不同的内存区域,但是两个内存区域里面的内容是一样的。

浅复制示意图:

9d52f823f2882c6c1083f068402149e7.png

深复制示意图:

b55d5c5175f3a0717785a316fb562666.png

iOS开发中,浅复制和深复制要更复杂一些,涉及到集合对象和非集合对象的copy与mutableCopy。

非集合对象:如NSString,NSInteger,NSNumber……

集合对象:如NSArray,NSDictionary,……

1:非集合对象的copy与mutableCopy。

非集合对象的copy与mutableCopy,只需要遵循以下规则即可:

(1)可变对象的copy和mutableCopy方法都是深复制

(2)不可变对象的copy方法是浅复制,mutableCopy方法是深复制

(3)copy方法返回的对象是不可变对象

下面通过代码来验证:

可变对象的copy与 mutableCopy方法:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testMutable()

{

//可变对象的复制,copy和mutableCopy都是深拷贝

NSMutableString *str1 = [NSMutableString stringWithString:@"test"];

NSMutableString *str2 = [str1 copy];

//copy返回的是不可变对象,因此str2不能改变,会发生崩溃

//[str2 appendString:@"test"];

NSMutableString *str3 = [str1 mutableCopy];

[str3 appendString:@"test"];

NSLog(@"%@ %@ %@",str1,str2,str3);

NSLog(@"%p %p %p",str1,str2,str3);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

cb144d3685ba2c161f0e6d0a3c5c07ad.png

可以看到,三个字符串的地址是不相同的,说明copy和 mutableCopy方法都是深复制。

不可变对象的copy与mutableCopy方法:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testNoMutable()

{

NSString *str1 = @"test";

//直接copy是浅复制

NSMutableString *str2 = [str1 copy];

//copy返回的是不可变对象,str2不能被修改,因此会发生崩溃

//[str2 appendString:@"test"];

//mutableCopy是深复制

NSMutableString *str3 = [str1 mutableCopy];

[str3 appendString:@"test"];

NSLog(@"%@ %@ %@",str1,str2,str3);

NSLog(@"%p %p %p",str1,str2,str3);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

fe40ce5632603cfbcd44cbf340320330.png

可以看到:前两个地址一样,第三个地址不一样,因此不可变对象的copy方法是浅复制,mutableCopy方法是深复制。

另外需要注意:无论是可变对象还是不可变对象,copy 方法返回的对象都是不可变的。

2:集合对象的copy与mutableCopy

实际上,集合对象与非集合对象所遵循的规则基本上是一样的。

可变对象的的copy与mutableCopy 方法

验证代码:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testSetMutable()

{

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

//可变对象copy是深复制

NSMutableArray *array2 = [array1 copy];

//copy返回的是不可变对象,array2不能被修改,因此会崩溃

//[array2 addObject:@"d"];

//可变对象的mutableCopy是深复制

NSMutableArray *array3 = [array1 mutableCopy];

[array3 addObject:@"d"];

NSLog(@"%p %p %p",array1,array2,array3);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

f4a7d53ec8eaf13ff4959b60571d28e7.png

可以看到地址是不一样的。说明可变对象的copy和mutableCopy方法都是深复制。

不可变对象的copy与mutableCopy方法

验证代码:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testSetNoMutable()

{

NSArray *array1 = @[@"a",@"b",@"c"];

//不可变对象的copy方法,浅复制

NSArray *array2 = [array1 copy];

//不可变对象的mutableCopy方法,深复制

NSArray *array3 = [array1 mutableCopy];

NSLog(@"%p %p %p",array1,array2,array3);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

0e379107200cc95e351c2492bc5c56d0.png

可以看到,前两个地址一样,第三个地址不一样。说明不可变对象的copy方法是浅复制,mutableCopy方法是深复制。

集合对象和非集合对象的一个差别:

上面说的集合对象的深复制并不是严格意义上的深复制,而是单层深复制。

单层深复制:对集合对象来说,深复制时只是将第一层对象进行了深复制,内部的对象仍然是浅复制。比如说

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

调用copy方法   NSArray *array2 = [array1 copy] ,有分配了一块内存,array2指向了这块内存,但是数组内部的元素,指向的仍然是数组1内部的元素,即内部元素是浅复制。

验证代码:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testSetMutable()

{

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

//可变对象copy是深复制

NSMutableArray *array2 = [array1 copy];

//copy返回的是不可变对象,array2不能被修改,因此会崩溃

//[array2 addObject:@"d"];

//可变对象的mutableCopy是深复制

NSMutableArray *array3 = [array1 mutableCopy];

[array3 addObject:@"d"];

NSLog(@"%p %p %p",array1,array2,array3);

NSLog(@"%p %p %p",array1[0],array2[0],array3[0]);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

bc05606cbd3a022c81652f43549048f3.png

可以看到,三个数组的第一个元素的地址是一样的,也就是说内部元素是浅复制。

3:集合对象的完全复制

集合对象的完全复制,就是集合中的每一层的元素都是深复制。

方法一:

使用 initWith***: copyItems:YES  方法。

代码:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testFullCopy()

{

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

NSArray *array2 = [[NSArray alloc] initWithArray:array1 copyItems:YES];

NSLog(@"%p %p",array1,array2);

NSLog(@"%p %p",array1[0],array2[0]);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

af9e04651adcbcef6f00a55ef3405a61.png

可以看到数组元素的地址不一样。

方法二:

先将集合进行归档,然后再解档。代码如下:

9de3cf8f74deb3254ceb788353b8e9b3.gif

void testFullCopy2()

{

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

NSArray *array2 = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1 ] error:nil];

NSLog(@"%p %p",array1,array2);

NSLog(@"%p %p",array1[0],array2[0]);

}

9de3cf8f74deb3254ceb788353b8e9b3.gif

执行结果:

e5c5f82bf709fe6f30c780e405cb906e.png

可以看到数组元素的地址不一样。

(责任编辑:最模板)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值