iOS深拷贝与浅拷贝
这篇文章的技术来源支持是https://www.jianshu.com/p/cf34d7ed180d
在写文章之前我一直认为,iOS的深拷贝就是对地址的拷贝,浅拷贝就是对指针的复制,最大的区别在于是否开辟新的地址空间。
但iOS官方文档对深拷贝与浅拷贝的定义确是:
There are two kinds of object copying: shallow copies and deep copies. The normal copy is a shallow copy that produces a new collection that shares ownership of the objects with the original. Deep copies create new objects from the originals and add those to the new collection.
翻译过来就是:对象复制有两种:浅拷贝和深拷贝。普通副本是一个浅拷贝,它生成一个与原始副本共享对象所有权的新集合。深度副本从原始副本创建新对象并将其添加到新集合中。
In the case of these objects, a shallow copy means that a new collection object is created, but the contents of the original collection are not duplicated—only the object references are copied to the new container.
A deep copy duplicates the compound object as well as the contents of all of its contained objects.
对于这些对象,浅拷贝意味着创建一个新的集合对象,但是原始集合的内容不是复制的——只有对象引用被复制到新的容器中。深度复制复制复合对象及其所有包含对象的内容。
看到这很多人可能有点懵,到底是什么意思?
简言之:
1.对深浅拷贝的判断首先得确认当前对象是否是容器对象
2.非容器对象(例:NSMutableString、NSString):对于系统的非容器类对象,我们可以认为,如果对不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。copy返回的对象是不可变的,mutableCopy是可变的。
3.系统容器对象(例:NSArray、NSMutableArray、NSDictionary、NSMutableDictionary):copy操作返回的必然是一个不可变对象,无论源对象是可变对象还是不可变对象。如果源对象是一个不可变对象,那么它们(源对象和新生成的对象)指向同一个对象,如果源对象是可变对象,它们指向不同对象。mutableCopy返回的必然是一个可变对象,无论源对象是可变对象还是不可变对象,它们(源对象和新生成的对象)仍指向不同地址,是两个对象。
特别注意的是:对于集合类的可变对象来说,深拷贝并非严格意义上的深复制,只能算是单层深复制,即虽然新开辟了内存地址,但是存放在内存上的值(也就是数组里的元素仍然之原数组元素值,并没有另外复制一份),这就叫做单层深复制。
说到这里,那到底是什么意思,依然是懵的?
当然对不可变对象NSString、NSArray、NSDictionary的copy操作确实是浅拷贝,因为真的只单纯多添加了条指针指向当前的存储空间,并没有开辟新的地址空间,肯定是浅拷贝

但是对不可变对象的拷贝也是浅拷贝,或者说单层深拷贝,开辟了新的存储空间(即新的容器),但并没有复制内容,新的地址里面的内容依然指向同一个内容空间。

就上面图而言,新拷贝的b[0]的值改变,a[0]的值也会改变,但是如果b新增一条数组,当前内容是新开辟的地址,所以并不会对a数组产生影响。
还有具体的懒得写了,看https://www.jianshu.com/p/cf34d7ed180d
上面文章写的很详细,如果实在看不明白,可以自己动手打印这么地址值试下
网友评论