最近又回忆了一下浅拷贝,深拷贝。之前理解的不够透彻,现在开始梳理一下。
OC语言中拷贝分为三类:浅拷贝,不完全深拷贝,完全深拷贝
浅拷贝:没有开辟新的指针地址,只是将新对象指向原来的指针,并没有进行真正的复制。如下图:
深拷贝:深拷贝分为不完全深拷贝,完全深拷贝
不完全深拷贝:开辟了新的指针地址,但是如果copy的对象是容器类(NSArray等),容器内的元素还是原来的元素(容器内的元素指针地址指向同一块内存)。不完全深拷贝拷贝的只是一个容器对象,只是外壳。容器内的对象只保存一份引用
可以看见,上面的数组内的元素地址是一样的,但是两个数组的指针地址并不一样
完全深拷贝:开辟了新的指针地址,而且如果拷贝的对象是容器类(NSArray等),容器内的元素同样也深拷贝了,开辟了新的内存空间,即容器内元素指针地址也改变了。完全深拷贝是连同容器和内容对象一起拷贝一份,完完全全的拷贝。使用系统方法:[NSAarray alloc]initWithArray:array1 copyItems: YES];进行完全深拷贝,但是只能拷贝里面的一层。
在上面的方法里,因为进行了深拷贝,所以,改变mutArray2[2]的元素的时候,是单独的改变,并不会影响mutArray3[2]的元素,看下面打印的结果
但是,我们如果改变深层次的元素呢,数组里面的数组元素呢。上面测试中,我分别打印了mutArray2[3][3] 和mutArray3[3][3] 的地址,发现两个是一样的,并未改变,(说明深拷贝没到这一层,只是不完全深拷贝),下面改变 mutArray2[3][3]里面的元素,那么mutArray3[3][3]里面的元素也会改变。
添加代码: mutArray2[3][3][3] = @“it will not copy”;看下图打印结果
里面的元素同时发生了改变,并且地址一样
拷贝的目的是产生两个互不影响的对象,所以:
1. 对于不可变的对象来说,由于对象本身不可以进行改变,即不能对它产生影响。所以不可变对象的copy都是浅拷贝
2.不可变对象的mutableCopy是深拷贝 (这里所指的深拷贝是不完全深拷贝)
3.可变对象的copy是深拷贝
4.可变对象的mutableCopy是深拷贝
以下是不完全深拷贝的理解
当我们修改copyArray的时候,并不会影响到Array,但是修改copyArray里的objc的时候,array里面的objc也会改变
以下是完全深拷贝的理解
完全深拷贝是连同容器和内容对象一起拷贝一份,完完全全的拷贝,我们不论是修改copyArray还是修改copyArray里面的objc都不会影响到array和array里面的objc
默认情况下的深拷贝都是不完全深拷贝,如果需要实现完全深拷贝,使用下面的方法:
对于容器对象,也完全遵守上面的情况,只不过发生深拷贝时对容器对象本身来说是深拷贝,因为产生了新对象,而对容器内的元素来说是浅拷贝。即:修改容器内的元素,无论是原来对象还是拷贝产生的新对象,两个容器内的元素都会发生改变,因为容器内存的是容器元素的内存地址。如果想让容器对象本身及容器内的元素都发生完全深拷贝,使用[NSAarray alloc]initWithArray:array1 copyItems: YES]; 才能真正的实现完全深拷贝。后面的item一定要设置为YES才是完全深拷贝(这句代码只能进行一次深拷贝,比如数组里多层嵌套数组,只会拷贝外面的那层,如果要多次进行深拷贝,需要用到归档和解档)
浅拷贝,深拷贝,完全拷贝的区别
浅拷贝,在浅拷贝操作时,对于被拷贝对象的每一层都是指针复制
深拷贝,在深拷贝操作时,对于被拷贝对象,至少有一层是深拷贝
完全拷贝,在完全拷贝操作时,对于被拷贝对象的每一层都是对象拷贝
以上是我从网上摘取深浅拷贝有关知识的整理,平时我一般用深浅copy很少,也就是需要对对象状态改变,进行比较的时候所用到过。。如果有不对的内容,请大家指出来。毕竟,交流使我们进步!