深拷贝浅拷贝

一直对深拷贝和浅拷贝模糊理解,在项目中遇到问题才知道自己没理解透彻。

浅拷贝:拷贝指针,指向原地址指针指向的内存,其实就是,浅拷贝出来的内容发生改变,原数据也会发生变化,因为原指针和拷贝出来的指针都指向同一块内存,通过指针找到内容,改变内容,那么两个当然都会发生变化。
深拷贝:创建一个新的指针,开辟一块新的内存,从原来内存里面拷贝一份数据的内容出来,并用新指针指向新内容的这块内存和原来的完全没有关系。不管是原数据改变还是拷贝内容的改变都不会影响到另一个

非集合对象

比较典型的是字符串, 通过查看NSString,可以知道字符串是遵循copy和mutableCopy协议的,所以可以直接使用 [string copy] 和 [string mutableCopy] 方法

@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>

首先是不可变的对象

NSString *string = @"123";
NSString *copyString = [string copy];
copyString = @"456";

打印结果:
string = 0x10a326020
copyString = 0x10a326020 
string = 123
ncopyString = 456

NSMutableString *mutableCopyString = [string mutableCopy];
[mutableCopyString appendString:@"你好"];

打印结果:
string = 0x10b967020
mutableCopyString = 0x6000014583c0
string = 123
mutableCopyString = 123你好

从上面可以看出来,对string 进行copy。没有开辟新的内存,因为原地址和拷贝出来的地址都指向同一块内容,所以拷贝出来的内容发生改变的时候,原内容也发生改变。
对string 进行mutableCopy,得到的是一个mutableString,原地址和拷贝出来的地址是两个不同的地址,不同的地址,指向不同的内存,所以改变拷贝出来的内容,不会影响到原内容,操作的不是同一块内存。

对可变对象

NSMutableString *string = [NSMutableString stringWithString:@"HelloWorld"];
NSString *copyString = [string copy];
NSMutableString *mutableCopyString = [string mutableCopy];
[mutableCopyString appendString:@"你好"];

打印结果
string = 0x60000275b210 = HelloWorld
copyString = 0x600002921c20 = HelloWorld
mutableCopyString = 0x60000277c870 = HelloWorld你好

对可变对象进行copy和mutableCopy操作,可以看到,得到的地址和原地址都不同,都进行了内容拷贝,都是深拷贝,操作任何一个都不会影响原内容

所以:
对不可变对象的copy是浅拷贝,对可变对象的copy是深拷贝;
对可变、不可变对象的mutableCopy都是深拷贝;
还有就是copy得到的类型一定是不可变的,mutableCopy得到的类型一定是可变的。

集合对象
NSArray 也遵循了NSCopying, NSMutableCopying 这两个协议,也就是支持copy和mutableCopy功能
对不可变数组进行copy

NSArray *array = @[[NSMutableString stringWithString:@"string1"],@"string2"];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSMutableString *firstObject = mutableCopyArray[0];
[firstObject appendString:@"-hahha"];
打印结果:
array = 0x60000240a5e0 = (
    string1-hahha,
    string2
)
copyArray =  0x60000240a5e0 = (
    string1-hahha,
    string2
)
mutableCopyArray = 0x600002a210b0 = (
    string1-hahha,
    string2
)
array.firstObject = 0x600002a21320 
copyArray.firstObject = 0x600002a21320 
mutableCopyArray.firstObject = 0x600002a21320

对不可变数组进行copy 是指针拷贝,只拷贝指针了
对不可变数组进行mutableCopy 地址发生了变化,是内容拷贝
但是,数组内容是浅拷贝,可以看到 三个数组第一个元素的指针从来都没变过,改变其中的一个,都会发生改变

对可变数组的copy和mutableCopy

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"strin1"],@"string2", nil];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
打印结果:
array = 0x600002f96220 = (
    strin1,
    string2
)
copyArray = 0x6000021fce40 = (
    strin1,
    string2
)
mutableCopyArray = 0x600002f96250 = (
    strin1,
    string2
)
array[0] = 0x600002f96100 = strin1
copyArray[0] = 0x600002f96100 = strin1
mutableCopyArray[0] = 0x600002f96100 = strin1

可以看到对可变数组进行copy 和 mutableCopy 得到的都是不同的地址,都进行了深拷贝,取每一个数组的第一个元素进行内容和地址的打印,地址都是一样的,也就是说,内容是指针拷贝

所以:得到的结论和上面是一样的,对于不可变的(集合对象)copy 是指针拷贝,mutableCopy是内容拷贝;对于可变的(集合对象)不管是copy还是mutablecopy都是内容拷贝。但是内部元素不管是copy 还是mutableCopy 都是指针拷贝,

实际项目用例:在网络请求得到一个可变数组,把可变数组传到VC里面,在VC里面有一个,VC里面有一个点击事件需要处理某一个model,从数组里面取出来,然后改变某个属性,refreshUI 就可以了,数组里面的元素是指针拷贝,取出来那个已经改变完了,就不用再去替换数组了

换个好理解的思路:mutableCopy 都是内容拷贝,对不可变对象的copy是指针拷贝,对可变对象的copy是深拷贝;

如何对集合的元素实现深拷贝

NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"string1"],@"string2", nil];
NSArray *deepCopyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
NSArray *deepCopyArray1 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
打印结果:
array = 0x600000f67160
deepCopyArray =0x600000f672e0
deepCopyArray1 = 0x600000f67360

array = [0x6000002f5e60,0x10779b148]
deepCopyArray = [0xc111a9c0f4d43203,0x10779b148]
deepCopyArray1 = [0x6000002f5c50,0xc121a9c0f4d43203]

可以看到数组都是新数组,新的内存空间,子元素也是新的内存空间,都实现了深拷贝。

自定义对象使用copy 和 mutableCopy需要遵守NSCopying 和 NSMutableCopying协议,实现- (id)copyWithZone:(nullable NSZone *)zone和-(id)mutableCopyWithZone:(nullable NSZone *)zone方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值