iOS 集合的深复制与浅复制
2019独角兽企业重金招聘Python工程师标准>>>
概念
对象拷贝有两种方式:浅复制和深复制。顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针;深复制是直接拷贝整个对象内存到另一块内存中。
一图以蔽之
再简单些说:浅复制就是指针拷贝;深复制就是内容拷贝。
________________________________________
集合的浅复制(shallow copy)
集合的浅复制有非常多种方法。当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合。
现在让我们看一些浅复制的例子:
1 2 3 4 5 6 |
|
集合的深复制(deep copy)
集合的深复制有两种方法。可以用initWithArray:copyItems:将第二个参数设置为YES即可深复制,如
1 |
|
如果你用这种方法深复制,集合里的每个对象都会收到copyWithZone:消息。如果集合里的对象遵循NSCopying协议,那么对象就会被深复制到新的集合。如果对象没有遵循NSCopying协议,而尝试用这种方法进行深复制,会在运行时出错。copyWithZone:这种拷贝方式只能够提供一层内存拷贝(one-level-deepcopy),而非真正的深复制。
第二个方法是将集合进行归档(archive),然后解档(unarchive),如:
1 |
|
________________________________________
集合的单层深复制(one-level-deep copy)
看到这里,有同学会问:如果在多层数组中,对第一层进行内容拷贝,其它层进行指针拷贝,这种情况是属于深复制,还是浅复制?对此,苹果官网文档有这样一句话描述
This kind of copy is only capable of producing a one-level-deep copy. If you only need a one-level-deep copy...
If you need a true deep copy, such as when you have an array of arrays...
从文中可以看出,苹果认为这种复制不是真正的深复制,而是将其称为单层深复制(one-level-deepcopy)。因此,网上有人对浅复制、深复制、单层深复制做了概念区分。
浅复制(shallowcopy):在浅复制操作时,对于被复制对象的每一层都是指针复制。
深复制(one-level-deepcopy):在深复制操作时,对于被复制对象,至少有一层是深复制。
完全复制(real-deepcopy):在完全复制操作时,对于被复制对象的每一层都是对象复制。
当然,这些都是概念性的东西,没有必要纠结于此。只要知道进行拷贝操作时,被拷贝的是指针还是内容即可。
________________________________________
系统对象的copy与mutableCopy方法
不管是集合类对象,还是非集合类对象,接收到copy和mutableCopy消息时,都遵循以下准则:
copy返回imutable对象;所以,如果对copy返回值使用mutable对象接口就会crash;
mutableCopy返回mutable对象;
下面将针对非集合类对象和集合类对象的copy和mutableCopy方法进行具体的阐述
1、非集合类对象的copy与mutableCopy
系统非集合类对象指的是NSString,NSNumber...之类的对象。下面先看个非集合类immutable对象拷贝的例子
1 2 3 |
|
通过查看内存,可以看到stringCopy和string的地址是一样,进行了指针拷贝;而stringMCopy的地址和string不一样,进行了内容拷贝;
再看mutable对象拷贝例子
1 2 3 4 5 6 7 8 9 |
|
运行以上代码,会在第7行crash,原因就是copy返回的对象是immutable对象。注释第7行后再运行,查看内存,发现string、stringCopy、mStringCopy、stringMCopy四个对象的内存地址都不一样,说明此时都是做内容拷贝。
综上两个例子,我们可以得出结论:
在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:
[immutableObjectcopy]//浅复制
[immutableObjectmutableCopy]//深复制
[mutableObjectcopy]//深复制
[mutableObjectmutableCopy]//深复制
2、集合类对象的copy与mutableCopy
集合类对象是指NSArray、NSDictionary、NSSet...之类的对象。下面先看集合类immutable对象使用copy和mutableCopy的一个例子:
1 2 3 |
|
查看内容,可以看到copyArray和array的地址是一样的,而mCopyArray和array的地址是不同的。说明copy操作进行了指针拷贝,mutableCopy进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝array这个对象,array集合内部的元素仍然是指针拷贝。这和上面的非集合immutable对象的拷贝还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看mutable对象拷贝的例子:
1 2 3 |
|
查看内存,如我们所料,copyArray、mCopyArray和array的内存地址都不一样,说明copyArray、mCopyArray都对array进行了内容拷贝。同样,我们可以得出结论:
在集合类对象中,对immutable对象进行copy,是指针复制,mutableCopy是内容复制;对mutable对象进行copy和mutableCopy都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:
[immutableObjectcopy]//浅复制
[immutableObjectmutableCopy]//单层深复制
[mutableObjectcopy]//单层深复制
[mutableObjectmutableCopy]//单层深复制
这个代码结论和非集合类的非常相似。
这时候,是不是有人要问了,如果要对集合对象复制元素怎么办?有这疑问的同学不妨回头看看集合的深复制。
好了,深复制与浅复制就讲到这里。
________________________________________
最后说个题外的东西,在搜集资料的过程中,发现一个有可能犯错的点
1 2 |
|
上面这段代码,在执行第二行代码后,内存地址发生了变化。乍一看,有点意外。按照C语言的经验,初始化一个字符串之后,字符串的首地址就被确定下来,不管之后如何修改字符串内容,这个地址都不会改变。但此处第二行并不是对str指向的内存地址重新赋值,因为赋值操作符左边的str是一个指针,也就是说此处修改的是内存地址。
所以第二行应该这样理解:将@"newStirng"当做一个新的对象,将这段对象的内存地址赋值给str。
我有如下的两个方法查看内存地址
pstr会打印对象本身的内存地址和对象内容
1 2 |
|
po&str则打印的是引用对象的指针所在的地址
1 2 |
|
转载于:https://my.oschina.net/u/2361492/blog/677111
iOS 集合的深复制与浅复制相关推荐
- IOS学习笔记十八(copy、mutableCopy、NSCopying、NSMutableCopy、深复制、浅复制)
1. copy.mutableCopy方法 copy方法返回对象的不可修改的副本 mutableCopy方法返回的对象可修改的副本 1).测试demo int main(int argc, char ...
- php对象当参数传递 php深复制和浅复制
把对象当参数传递给方法,在方法里改过对象后,影响到外面的对象 因为对象是引用传递过去的 class Book {public $name;public function __construct($n ...
- python列表浅复制_Python列表的深复制和浅复制示例详解
一.深复制与浅复制 列表是Python中自带的一种数据结构,在使用列表时,拷贝操作不可避免,下面简单讨论一下列表的深复制(拷贝)与浅复制 首先看代码: l1 = [5, 4, 3, 2, 1] # 用 ...
- C#中的深复制和浅复制(在C#中克隆对象)
C#中的深复制和浅复制(在C#中克隆对象) 转载于:https://www.cnblogs.com/dalovess/p/7002947.html
- python list 深复制_Python列表的深复制和浅复制示例详解
免费资源网,https://freexyz.cn/ 一.深复制与浅复制 列表是Python中自带的一种数据结构,在使用列表时,拷贝操作不可避免,下面简单讨论一下列表的深复制(拷贝)与浅复制 首先看代码 ...
- C++学习基础七——深复制与浅复制
C++学习基础七--深复制与浅复制 一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和c ...
- 深复制VS浅复制(MemberwiseClone方法介绍)
MemberwiseClone方法,属于命名空间System,存在于程序集 mscorlib.dll中.返回值是System.Object.其含义是:创建一个当前object对象的浅表副本. MSDN ...
- Objective-C 深复制和浅复制与NSCopying协议
1.简单复制只能实现浅拷贝:指针赋值,使两个指针指向相同的一块内存空间,操作不安全. 2. Foundation类已经遵守了<NSCopying>和 <NSMutableCopyin ...
- [C++]深复制与浅复制
深复制与浅复制 C++中,默认的复制构造函数只能实现浅复制. 浅复制指的是在对象复制前,只对对象中的数据成员进行简单的复制 大多数情况下"浅复制"已经能很好的工作了,但是当类的数据 ...
最新文章
- “中台不就是微服务吗?有啥区别?”
- R语言ggplot2可视化2d密度图:可视化二维密度图并将两个二维密度图重叠起来、Overlay two ggplot2 stat_density2d plots
- java递归url目录_Java递归实现某个目录下所有文件和目录
- UML学习---交互
- windows server 2003断开远程之后自动注销用户
- requests库详解
- AI 质检学习报告——学习篇——AI质检产生背景和发展过程
- 机器人语言特性探索2-正在发生的趋势
- jstack 脚本 自动日志_GitLab从安装到全自动化备份一条龙
- 16名本科生领衔的芯片公司 芯微电子要上市了?
- Johnson 算法 洛谷P5905
- 电子病历基本数据集_电子病历质控的三项是因素-病历质控系统助力提升电子病历质量...
- Android接入google地图
- V4L2视频采集的基本流程
- python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)
- SFDC Lightning Performance Tuning
- kettle命令运行工具(pan、kitchen、carte)
- [C#] 使用 NAudio 实现音频可视化
- 暗黑破坏神3难度的钥匙去哪里打?
- 《深入浅出数据分析》小结
热门文章
- matplotlib可视化_EDA:Geopandas,Matplotlib和Bokeh中的可视化
- 面试官问:能否模拟实现JS的call和apply方法
- network中的请求信息,headers中的每一项分别是什么意义?
- 安装pywin32时:ImportError: DLL load failed: %1 不是有效的 Win32 应用程序和 DLL load failed...
- 游戏安全资讯精选 2017年第十期 英国彩票网遭遇DDoS攻击,中断90分钟 DNSMASQ多高危漏洞公告 阿里云协助警方破获国内最大黑客攻击案,攻击峰值690G...
- Java学习优秀网站
- [APP]- 找回Xcode7的代码折叠功能
- Excel数据生成SQL insert语句
- ASP.NET性能优化之构建自定义文件缓存
- python的开发环境有哪些系统_Win10下配置机器学习python开发环境