004 copy/mutableCopy 与 浅拷贝/深拷贝

如题所述

第1个回答  2022-07-24

“为学日益,为道日损,损之又损,以至于无为,无为而无不为”。用自己的思考去理解问题,从问题的源头探索,才有可能寻找到最接近设计者思想的答案。网上有非常多的博客,博客内容良莠不齐,且绝大多数是为被大众证实,仅仅是一面之词。日常阅读,日常解惑,有这两篇文档可以阅读,分别是更新在MRR、ARC时代的两篇文章。

Updated: 2009-10-21
Memory Management Programming Guide for Core Foundation
Updated: 2012-07-17
Advanced Memory Management Programming Guide

下面只是笔者对上面两篇文章一点读后感。

引用拷贝 这个名词在文章中并没有直接指出,但有相关的概念提示,例如截图第二段中,第三行: copies the reference to the object ,第五行中提到: the reference is duplicated ,拷贝的结果是一个新的指针,故亦称之为 指针拷贝 。

下面以整数的拷贝为例:
myInt2 = myInt1

myCFString2 = myCFString1

上面提到了 CFStringCreateCopy ,这个方法仅仅是适用于字符串的copy,而对于array,同样有 CFArrayCreateCopy 方法。 CFxxtypexxCreateCopy 系列的方法都会拷贝一个新的对象。

例如CFStringRef、CFDataRef,在使用 CFxxtypexxCreateCopy 时,都会拷贝一个全新的对象。

从上面的一些特点不难分析出, 深拷贝是一种概念 ,而不是某个具体的操作。不管是集合对象,还是自定义的实例对象,除了对象本身,他们还依赖一些其他对象,我们可以通过引用的方式来表示其他对象。当对象本身被拷贝时,仅仅只会开辟这个对象需要的空间,然后将原对象中的数据一比一复制一份存到这块内存,到这里就是浅拷贝的过程。如果是深拷贝,还需要把所有引用指向的对象再拷贝一份,让引用也指向新的对象,这样才能将这个对象以及这个对象所依赖的其他对象完全与原来的那份隔离开。
满足以下两个过程的拷贝可以称作深拷贝:

上面仅仅是对平时一直遇到,但没有理解透彻的概念做了一个整理,加深对这些概念的理解。上面的三个拷贝都是在MRR模式下, Core Foundation 框架中的概念,而且有API支持。在ARC模式下,我们遇到最多的其实是 strong/copy/mutableCopy 这些关键词。

这张图可以佐证上面的一些概念。 Foundation 框架中的 copy 只表示一件事—— 拷贝对象 ,所以 copy 与 浅拷贝、深拷贝 的概念无直接联系。在ARC中的 copy 可以理解为MRR中的 CreateCopy —— The Create Rule

上述案例介绍了 create 和 copy 的规则,与上面分析的一致,而且完全没有提到任何关于 mutable 相关的解释。下面再看一个API的定义

CFArrayCreateMutableCopy

根据上面对 深拷贝概念 的对比,发现 mutableCopy 并没有完成深拷贝的过程,仅仅只是一个浅拷贝的过程。与 copy 不同的是,返回的容器对象是可变的,两者差异仅此而已。对容器对象,有以下特点:

那么在 Foundation 框架中要完成深拷贝,可以使用框架提供的API:

initWithArray:copyItems:

明确每一种概念所发生的变化,相关的问题都将迎刃而解。

Memory Management Programming Guide for Core Foundation
Advanced Memory Management Programming Guide
The Create Rule
CFArrayCreateMutableCopy
initWithArray:copyItems:

相似回答