深浅拷贝
目录
1.定义
浅拷贝:浅拷贝就是创建一个新对象,该对象与原始对象共享内部数据的引用。也就是说,浅拷贝就是创建一个存放与复制对象相同地址的指针变量,也称为指针拷贝
深拷贝:深拷贝是指创建一个新对象,并复制原始对象及其引用的所有数据。深复制会递归地复制对象的所有内容,包括对象所引用的其他对象。这样,原始对象和副本对象拥有独立的内存空间,彼此之间的修改互不影响。也就是说深拷贝创建了一个与被复制的对象的值完全相同的对象,但是他们的地址是不同的,也称为内容拷贝
2.可变与非可变类的copy与mutable copy
其实有关容器类和非容器类,他们的深浅拷贝都是一样的,总结下来就是不可变类copy是浅拷贝,mutablecopy是深拷贝,可变类copy和mutablecopy都是深拷贝。
这是非容器类的深浅拷贝对比,运行结果如下:
容器类的如下:
可变类 | 不可变类 | |
---|---|---|
copy | 深拷贝 | 浅拷贝 |
mutablecopy | 深拷贝 | 深拷贝 |
3.容器类里的元素都是浅拷贝
虽然对容器类进行copy或者mutablecopy操作与非容器类相同,但对于容器类的元素,都是浅拷贝。
由以上可见容器类中的元素在拷贝后地址都相同,也就意味着都是浅拷贝。
4.自定义类的深浅拷贝
有关于自定义类,对于这个类本身,无论copy还是mutablecopy都是深拷贝,但是对于类中指针类型的属性,如果使用=或者copy,那么该属性是浅拷贝,如果调用mutablecopy方法,那么该属性是深拷贝。注意⚠️:想要对自定义类调用copy或者mutablecopy时,要遵守NScopying或者NSMutableCopying协议,重写copywithzone或者mutablecopywithzone方法。
这里重写copywithzone时,对字符串属性用的是=,重写mutablecopywithzone时,对字符串属性用的是muatblecopy。代码运行结果如下:
也就意味着,对于自定义类,对该类拷贝都是深拷贝,但是类中指针类型的属性深浅拷贝由重写的方法决定
5.属性关键字copy与strong
在定义属性时,可以选择copy或者strong关键字来修饰,选择copy还是strong有一些区别。
这里代码中的export属性就是用copy修饰的,当试图用appendString去修改时,会看到程序编译出现了错误,提示:“试图修改一个不可修改的变量”。其实是因为copy关键字,就相当于在对属性赋值的时候调用了一次copy方法,那么得到的属性就已经变成不可变类型了,自然就不能调用方法修改了。所以,在选择关键字时,一般可变类使用strong,不可变类使用copy。
6.容器类对象的完全深拷贝
对于容器类对象,之前提到容器类中的元素全都是浅拷贝,那么如何实现容器类对象的完全深拷贝呢?有如下三种方法
copyitems
copyitems是oc提供的一种初始化方法,当可以直接通过该方法对容器进行完全深拷贝
copyitems用于创建一个新的数组,并对数组中的元素进行拷贝。该方法会遍历原始数组的每个元素,并对每个元素执行 copy 操作,然后将拷贝后的元素添加到新的数组中。
但是,当容器类的元素是指针类型(比如字符串、容器)时,就无法实现完全深拷贝。
递归复制属性
那么遇到指针类型的元素,或者属性时,我们就要递归的复制属性,对每一个属性进行深拷贝,就可以实现完全深拷贝。
也就是上文提到在自定义类中对字符串等这样的指针变量调用mutablecopy方法进行深拷贝,由于上文已经阐述过,这里就不用代码演示了
解档与归档
这个方法笔者暂时还没有深入学习,以后再来补充