所有系统容器类的copy或mutableCopy方法,都是浅拷贝!!!

(ps:什么是容器?比如NSArray,NSMutableArray,NSDictionary,NSMutableDictionary)

很多人一直认为,copy 是浅拷贝,mutableCopy 是深拷贝。我以前也是这么认为的。甚至很多网上的教学视频,很多书籍,很多博客,都是这么说的。但是,这大错特错!

为了防止有人不信,我们先拿出决定性的证据,然后再说其他的。

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.

以上三句出自于苹果官方文档 Collections.pdf。

看不懂?没关系。我大致翻译一下。

有两种类型的对象拷贝,浅拷贝和深拷贝。正常的拷贝,生成一个新的容器,但却是和原来的容器共用内部的元素,这叫做浅拷贝。深拷贝不仅生成新的容器,还生成了新的内部元素。

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.

以上两句出自于苹果官方文档 CFMemoryMgmt.pdf。

这个翻译过来和上面的意思几乎一样。

OK,有官方文档为证。现在我们至少可以明确地、大声地说出来:浅拷贝复制容器,深拷贝复制容器及其内部元素

这点毋庸置疑了吧?

如果你看到这里,那说明你对 “浅拷贝复制容器,深拷贝复制容器及其内部元素“ 这句话没有疑问了。

好,下面我们来验证本文的题目:所有系统容器类的copy或mutableCopy方法,都是浅拷贝!!!。上代码:

  1. NSMutableArray *element = [NSMutableArray arrayWithObject:@1];
  2. NSMutableArray *array = [NSMutableArray arrayWithObject:element];

现在我们有一个可变数组,它的名字是 array。

它只有一个元素,叫做 element。

它的这个唯一的元素是一个可变数组。

请在往下看之前确保你理解了上面这三句话。

  1. NSMutableArray mutableCopyArray = [array mutableCopy];

现在,我们对 array 进行了 mutableCopy,生成了一个新的可变数组,名字叫做 mutableCopyArray。

  1. [mutableCopyArray[0] addObject:@2];

array 的第一个元素是一个数组对吧。

mutableCopyArray 的第一个元素也是一个数组对吧。

现在我改变了 mutableCopyArray 的元素,往这个元素里加了一个 2。

现在输出 array[0] 看看,结果是 1 和 2。

为什么我们修改了 mutableCopyArray 的元素,结果 array 的元素也跟着改变了呢?

因为二者的元素是共用的。

也就是说,mutableCopy 只复制了容器(此处也就是数组),但是没有复制容器内的元素。

结合官方文档,结论:mutableCopy 是浅拷贝。

不相信?事实摆在眼前,有什么不可相信的?就因为你看的那些视频?那些博客?他们说的就是对的,就不会错了吗?

此外,当你问别人什么是深拷贝什么是浅拷贝的时候,如果他拿 NSString 或者 NSMutableString 给你举例子,那么请你别信,因为他也是在扯淡。

copy
与 mutableCopy 不等同于浅拷贝与深拷贝。

拷贝是针对容器类型和自定义类的,字符串根本就不是容器,还谈什么深拷贝浅拷贝???



说了半天 copy 和 mutableCopy 都是浅拷贝,那到底怎么才是深拷贝?

可以用系统中的
initWithArray:copyItems: 方法,比如:

  1. NSArray *deepCopyArray = [[NSArray alloc] initWithArray:someArray copyItems:YES];

也可以用我们自定义的方法,比如:

  1. - (NSArray *)test_deepCopy {
  2. NSMutableArray *array = [NSMutableArray array];
  3. for (id element in self) {
  4. id copyElement = nil;
  5. if ([element respondsToSelector:@selector(test_deepCopy)]) {
  6. copyElement = [element test_deepCopy];
  7. }
  8. else if ([element respondsToSelector:@selector(copyWithZone:)]) {;
  9. copyElement = [element copy];
  10. }
  11. else {
  12. copyElement = element;
  13. }
  14. [array addObject:copyElement];
  15. }
  16. NSArray *result = [NSArray arrayWithArray:array];
  17. return result;
  18. }
  19. - (NSMutableArray *)test_mutableDeepCopy {
  20. NSMutableArray *array = [NSMutableArray array];
  21. for (id element in self) {
  22. id copyElement = nil;
  23. if ([element respondsToSelector:@selector(test_mutableDeepCopy)]) {
  24. copyElement = [element test_mutableDeepCopy];
  25. }
  26. else if ([element respondsToSelector:@selector(mutableCopyWithZone:)]) {
  27. copyElement = [element mutableCopy];
  28. }
  29. else if ([element respondsToSelector:@selector(copyWithZone:)]) {
  30. copyElement = [element copy];
  31. }
  32. else {
  33. copyElement = element;
  34. }
  35. [array addObject:copyElement];
  36. }
  37. return array;
  38. }

我们来总结一下:

所有系统容器类的copy或mutableCopy方法,都是浅拷贝!!!

浅拷贝复制容器,深拷贝复制容器及其内部元素

copy
与 mutableCopy 不等同于浅拷贝与深拷贝。

拷贝是针对容器类型和自定义类的,字符串根本就不是容器,还谈什么深拷贝浅拷贝???

如果面试官问你什么是深拷贝什么是浅拷贝,请自信地回答他。

如果他不认同你说的,请自信地拿出官方文档给他看。

copy和mutableCopy都是浅拷贝!!!------你被骗了很多年的更多相关文章

  1. 对copy、mutableCopy理解

    Objective - C 中有很多在日常项目中经常用到的常用代码,在这里着重的讲一下关于copy 和 mutableCopy 的区别以及相关用法. Objective - C 中可变对象和不可对象经 ...

  2. copy 和 MutableCopy

    1:copy拷贝得到的对象都是不可变对象,MutableCopy拷贝得到的对象都是可变对象.MutableCopy拷贝得到的对象都是新的对象,会重新分配内存地址,而copy拷贝的对象既可以是新对象,也 ...

  3. Copy与mutableCopy的个人理解

    Copy与mutableCopy的个人理解 1. 相同点 都是将原有对象进行深拷贝(狭义) 这里的狭义上的深拷贝指的是在不考虑编译器在编译时对不可变对象进行copy时采取的优化策略:即将不可变对象的地 ...

  4. [Objective-C] Copy 和 MutableCopy

    看了几篇文章,因为文章很新手向,所以内容很繁琐.故整理一下重点,写了测试程序去了解几个知识点,不讨论基本概念.新博客wossoneri.com传送门 非集合类对象的copy与mutableCopy / ...

  5. 【转】copy 和 mutablecopy (深拷贝和浅拷贝)

    阅读本文之前首先了解copy与retain的区别,如果有不正确的地方望大家多多指教: copy与retain的区别: copy是创建一个新对象,retain是创建一个指针,引用对象计数加1.Copy属 ...

  6. copy和mutableCopy的深、浅拷贝

    对象拷贝主要由两种方式:copy和mutableCopy.浅拷贝是指直接将指针指向原有的地址,从而达到复制的目的.深拷贝是指重新生成一个对象,将原有对象的内容复制到新的对象中.copy 返回的是一个不 ...

  7. Copy 与MutableCopy的区别

    NSString *string = @"origion"; NSString *stringCopy = [string copy]; NSMutableString *stri ...

  8. iOS Copy 和 MutableCopy的区别 深浅拷贝的区别-供参考

    概述 对于系统的非容器类对象,对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝).如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的. 对于 ...

  9. 关于:1.指针与对象;2.深浅拷贝(复制);3.可变与不可变对象;4.copy与mutableCopy的一些理解

    最近对深浅拷贝(复制)做了一些研究,在此将自己的理解写下来,希望对大家有所帮助.本人尚处在摸索阶段,希望各位予以指正. 本文包括如下方向的探索: 1.指针与对象: 2.深/浅拷贝(复制): 3.可变/ ...

随机推荐

  1. Swift 细节

    1.swift ?和 !的区别 1.1 Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化.如果在使 ...

  2. NodeJS项目迁移兼Ubuntu下NodeJS环境部署

    前言 之前做的几个项目都托管在阿里云服务器,但是最近要到期了.想着到底要不要续期,毕竟100/月.后面看着阿里云有个活动,800/三年.果断买下.环境部署折腾了一天,其中也遇到几个坑. 目录 一.安装 ...

  3. There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

    解题思路:合并两个数组,创建一个 Map对象,用以存放排好顺序的键值对,键为序号,值为数组值,中位数的结果分两种情况讨论: 1.m+n为奇数:(m+n)/2为中位数 2.m+n为偶数:(((m+n)/ ...

  4. IIS下防止mdb数据库被下载的实现方法

    第一种方法:要求网站管理人员具体asp编程经验.因为现在的销售虚拟主机的系统,已经为用户建立了一个database目录,跟web目录同一个级别,用户访问的是web中的文件,而无法访问database目 ...

  5. Android Studio设置快捷键和背景

    1.快捷键设置 复制代码并且向下移动 向下移动代码 代码提示 代码改错 更改文件名称   alt + shift + R   2.更改背景颜色-豆绿色           来自为知笔记(Wiz)

  6. 在linux环境下安装Node

    liunx安装node的方法 cd /usr/src //node 安装的位置   一 : 普通用户: 安装前准备环境: 1.检查Linux 版本 命令: cat /etc/redhat-releas ...

  7. Guava Cache源码解析

    概述: 本次主要是分析cache的源码,基本概念官方简介即可. 基本类图: 在官方的文档说明中,Guava Cache实现了三种加载缓存的方式: LoadingCache在构建缓存的时候,使用buil ...

  8. easyui datagrid自定义按钮列,即最后面的操作列(转)

    做项目的时候因为需求,要在表格的最后添加一列操作列,easyUI貌似没有提供这种功能,不过没关系,我们可以自定义来实现 版本:jQuery easyUI 1.3.2 这里我的实现方式是采用HTML形式 ...

  9. Linux桌面环境GNOME实用技巧

    GNOME是Linux桌面上主流的集成桌面环境之一,GNOME桌面以其风格简洁.操作便捷而受到Linux用户的欢迎.这里将介绍Linux桌面环境GNOME的操作技巧,在这里拿出来和大家分享一下. 下面 ...

  10. wmic 获得系统硬件信息

    wmic扩展了wmi系统管理指令,提供了命令行接口和批处理执行系统管理的工具.通过别名机制将命令转为对wmi命名空间的操作 1.获得cpu信息 2.获得cpu 核数 3.获得内存条信息