Objective-C 之深拷贝和浅拷贝
3月箴言
人的思想是了不起的,只要专注于某一项事业,就一定会做出使自己感到吃惊的成绩来。—— 马克·吐温
1、iOS中关于深拷贝和浅拷贝的概念
浅拷贝:浅拷贝并不拷贝对象本身,只是对指向对象的指针进行拷贝
深拷贝:直接拷贝对象到内存中一块区域,然后把新对象的指针指向这块内存
在iOS中并不是所有对象都支持Copy和MutableCopy,遵循NSCopying协议的类可以发送Copy协议,遵循NSMutableCopying协议的类可以发送MutableCopy消息。如果一个对象没有遵循这两个协议而发送Copy或者MutableCopy消息那么会发生异常。如果要遵循NSCopying协议,那么必须实现copyWithZone方法。如果要遵循NSMutableCopying协议那么必须实现mutableCopyWithZone方法。
2、可变对象和不可变对象调用深拷贝和浅拷贝方法的区别以及具体示例:
2.1非容器类不可变对象
- (void)immutableStrCopyAndMutCopy
{
NSString *immutableStr = @"不可变字符串";
NSMutableString *immutableStrCopy = [immutableStr copy];
NSMutableString *immutableStrMutCopy = [immutableStr mutableCopy];
// [immutableStrCopy appendString:@"22"];
[immutableStrMutCopy appendString:@""];
NSLog(@"immutableStrMutCopy = %@",immutableStrMutCopy);
/*
immutableStr_p = 0x107a58068 immutableStr = __NSCFConstantString
immutableStrCopy_p = 0x107a58068 immutableStrCopy = __NSCFConstantString,
immutableStrMutCopy_p = 0x6000034e07e0,immutableStrMutCopy= __NSCFString
__NSCFConstantString 表示对象存储在常量区,__NSCFString表示对象存储在堆上
*/
NSLog(@"\n immutableStr_p = %p immutableStr = %@ \n immutableStrCopy_p = %p immutableStrCopy = %@,\n immutableStrMutCopy_p = %p,immutableStrMutCopy= %@",immutableStr,[immutableStr class],immutableStrCopy,[immutableStrCopy class],immutableStrMutCopy,[immutableStrMutCopy class]); }
非容器类不可变对象 执行copy 和 mutbleCopy
结论:
对非容器类的不可变对象 执行copy 是浅拷贝,地址相同,返回的也是不可变对象
执行mutableCopy 是深拷贝,地址不同,返回的是可变对象
2.2非容器类可变对象
- (void)mutableStrCopyAndMutCopy
{
NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变字符串"]; NSMutableString *mutableStrCopy = [mutableStr copy];
//copy 之后 变为不可变对象,不可执行拼接操作,窒息该操作,直接崩溃!!
// [mutableStrCopy appendString:@"copy 之后拼接"];
NSMutableString *mutableStrMutCopy = [mutableStr mutableCopy];
[mutableStrMutCopy appendString:@"mutcopy"];
/*
mutableStr.p = 0x600001589230 mutableStr.class = __NSCFString mutableStr = 可变字符串
mutableStrCopy.p = 0x6000015890b0 mutableStrCopy.class = __NSCFString,mutableStrCopy = 可变字符串
mutableStrMutCopy.p = 0x6000015887b0,mutableStrMutCopy.class= __NSCFString,mutableStrMutCopy = 可变字符串mutcopy
*/
NSLog(@"\n mutableStr.p = %p mutableStr.class = %@ mutableStr = %@ \n mutableStrCopy.p = %p mutableStrCopy.class = %@,mutableStrCopy = %@\n mutableStrMutCopy.p = %p,mutableStrMutCopy.class= %@,mutableStrMutCopy = %@",mutableStr,[mutableStr class],mutableStr,mutableStrCopy,[mutableStrCopy class],mutableStrCopy,mutableStrMutCopy,[mutableStrMutCopy class],mutableStrMutCopy); }
非容器类可变对象执行 copy 和 mutableCopy
结论:
对于非容器类的可变对象 执行 copy 深拷贝,地址不同,返回的是不可变对象
执行mutableCopy,深拷贝,地址不同,返回的是可变对象
2.3容器类不可变对象
- (void)imArrayCopyAndMutCopy
{
NSString *immutableStr = @"不可变对象";
NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变对象兮"];
NSArray *imArray = [NSArray arrayWithObjects:immutableStr,mutableStr, nil];
NSArray *imArrayCopy = [imArray copy];
NSArray *imArrayMutCopy = [imArray mutableCopy];
/*
imArray.p = 0x60000259d960 imArray.class = __NSArrayI
imArrayCopy.p = 0x60000259d960 imArrayCopy.class = __NSArrayI
imArrayMutCopy.p = 0x600002b839f0,imArrayMutCopy.class= __NSArrayM
2019-03-03 12:13:35.401764+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x1098d4088,tempStr = __NSCFConstantString,tempStr.class = 不可变对象
2019-03-03 12:13:35.401864+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x600002b83b70,tempStr = __NSCFString,tempStr.class = 可变对象兮
2019-03-03 12:13:35.401945+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x1098d4088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可变对象
2019-03-03 12:13:35.402043+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x600002b83b70,tempCopyStr = __NSCFString,tempCopyStr.class = 可变对象兮
2019-03-03 12:13:35.402111+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x1098d4088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可变对象
2019-03-03 12:13:35.402171+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x600002b83b70,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可变对象兮
*/
NSLog(@"\n imArray.p = %p imArray.class = %@ \n imArrayCopy.p = %p imArrayCopy.class = %@\n imArrayMutCopy.p = %p,imArrayMutCopy.class= %@",imArray,[imArray class],imArrayCopy,[imArrayCopy class],imArrayMutCopy,[imArrayMutCopy class]); for (id tempStr in imArray) {
NSLog(@"imArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@\n",tempStr,[tempStr class],tempStr);
}
for (id tempCopyStr in imArrayCopy) {
NSLog(@"imArrayCopy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@\n",tempCopyStr,[tempCopyStr class],tempCopyStr);
} for (id tempMutCopyStr in imArrayMutCopy) {
NSLog(@"imArrayMutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@\n",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr);
} }
容器类对象 copy或mutableCopy (本方法是针对数组)
结论:对于容器类的不可变对象 执行copy 对于容器来说是浅copy,地址相同,且返回的是不可变对象
执行mutableCopy 对于容器来说是深拷贝,地址不同,且返回的是可变对象。
对于容器内的对象(可变或不可变对象)而言,无论容器执行的是copy还是mutableCopy,这些对象执行的都是浅拷贝
2.4容器类可变对象
- (void)mutArrayCopyAndMutCopy
{
NSString *immutableStr = @"不可变对象";
NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变对象兮"];
NSMutableArray *mutArray = [NSMutableArray arrayWithObjects:immutableStr,mutableStr, nil]; /*
mutArray.p = 0x600002c17000 mutArray.class = __NSArrayM
mutArray.copy.p = 0x60000221ace0 mutArray.copy.Class = __NSArrayI
mutArray.mutCopy.p = 0x600002c16fd0,mutArray.mutCopy.p= __NSArrayM
2019-03-03 12:24:00.751299+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x10ec73088,tempStr = __NSCFConstantString,tempStr.class = 不可变对象
2019-03-03 12:24:00.751410+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x600002c17330,tempStr = __NSCFString,tempStr.class = 可变对象兮
2019-03-03 12:24:00.751502+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x10ec73088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可变对象
2019-03-03 12:24:00.751594+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x600002c17330,tempCopyStr = __NSCFString,tempCopyStr.class = 可变对象兮
2019-03-03 12:24:00.751694+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x10ec73088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可变对象
2019-03-03 12:24:00.751789+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x600002c17330,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可变对象兮
*/
NSLog(@"\n mutArray.p = %p mutArray.class = %@ \n mutArray.copy.p = %p mutArray.copy.Class = %@\n mutArray.mutCopy.p = %p,mutArray.mutCopy.p= %@",mutArray,[mutArray class],[mutArray copy],[[mutArray copy] class],[mutArray mutableCopy],[[mutArray mutableCopy] class]);
for (id tempStr in mutArray) {
NSLog(@"mutArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@\n",tempStr,[tempStr class],tempStr);
}
for (id tempCopyStr in [mutArray copy]) {
NSLog(@"mutArray.copy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@\n",tempCopyStr,[tempCopyStr class],tempCopyStr);
} for (id tempMutCopyStr in [mutArray mutableCopy]) {
NSLog(@"mutArray.mutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@\n",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr);
}
}
容器类可变对象 copy和mutableCopy (本方法是针对数组)
结论:对于容器类可变对象 执行copy,深拷贝,地址不同,返回的是不可变对象
执行mutableCopy,深拷贝,地址不同,返回的是不可变对象
容器内的对象(无论可变或不可变),均为浅拷贝(地址相同)
- (void)imDicCopyAndMutCopy
{
NSString *immutableStrOne = @"不可变对象1";
NSMutableString *mutableStrOne = [NSMutableString stringWithFormat:@"可变对象1"];
NSString *immutableStrTwo = @"不可变对象2";
NSMutableString *mutableStrTwo = [NSMutableString stringWithFormat:@"可变对象2"];
/*
immutableDic.p = 0x6000003d2400 immutableDic.class = __NSDictionaryI
immutableDic.copy.p = 0x6000003d2400 immutableDic.copy.class = __NSDictionaryI
immutableDic.mutcopy.p = 0x600002dc8e00,immutableDic.mutcopy.class= __NSDictionaryM
2019-03-03 12:37:08.098513+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1
2019-03-03 12:37:08.098588+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.098698+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.098785+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1
2019-03-03 12:37:08.098873+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1
2019-03-03 12:37:08.098950+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.099037+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.099140+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1
2019-03-03 12:37:08.160496+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1
2019-03-03 12:37:08.160610+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.160716+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1
2019-03-03 12:37:08.160811+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 */
NSDictionary *immutableDic = @{immutableStrOne:immutableStrOne,immutableStrTwo:mutableStrOne,mutableStrOne:immutableStrOne,mutableStrTwo:mutableStrOne}; NSLog(@"\n immutableDic.p = %p immutableDic.class = %@ \n immutableDic.copy.p = %p immutableDic.copy.class = %@\n immutableDic.mutcopy.p = %p,immutableDic.mutcopy.class= %@",immutableDic,[immutableDic class],[immutableDic copy],[[immutableDic copy] class],[immutableDic mutableCopy],[[immutableDic mutableCopy] class]); [immutableDic enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"immutableDic ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj); }]; [[immutableDic copy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"immutableDic.copy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj);
}]; [[immutableDic mutableCopy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"immutableDic.mutcopy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ \n",key,[key class],key,obj,[obj class],obj); }]; }
容器类对象 针对字典验证
结论:容器类不可变对象 字典和数组的结论是一致的,且对于字典中的key或value ,都是浅拷贝
可以简单整理为:不可变对象的copy,都是浅拷贝,地址相同,
可变对象的copy和mutablecopy,都是深拷贝,
copy方法返回的是不可变对象,mutableCopy返回的是可变对象,
容器对象内的对象始终是浅拷贝。
代码可点击github,项目内搜索关键字copy and mutableCopy
Objective-C 之深拷贝和浅拷贝的更多相关文章
- C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...
- Objective-C中的深拷贝和浅拷贝
在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...
- $.extend()的深拷贝和浅拷贝详细讲解
版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...
- JavaScript中面向对象的的深拷贝和浅拷贝
理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 : ...
- C++深拷贝与浅拷贝
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会调用拷贝构造函数: (1)一个对 ...
- C++的深拷贝与浅拷贝
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...
- Python赋值语句与深拷贝、浅拷贝的区别
参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...
- [C#进阶系列]专题一:深入解析深拷贝和浅拷贝
一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- OC中的深拷贝与浅拷贝
深拷贝(deep copy)与浅拷贝(shallow copy)的定义一直是有争论的. 一种理解是: 所谓的浅拷贝, 就是不完全的拷贝 NSString *s = @"123"; ...
随机推荐
- vs code上配置Scala
转自:https://www.cnblogs.com/steven-yang/p/5852988.html 百度的结果表达太奇怪,简单记一笔. 1.下载一个scala的压缩包,https://www. ...
- 解决servlet在web.xml中的路径跳转问题
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" ...
- 前端构建工具Gulp的学习和使用
前几天刚鼓捣了Grunt的使用,结果文档还没捂热,老大说我们还是用gulp吧,搞得我又得来整gulp,眼泪流成河了,真是不晓得底层人民的辛苦啊.不过经过对gulp的学习,发现很好用,比grunt舒服! ...
- OFDM正交频分复用---基础入门图示
@(162 - 信号处理) 整理转载自:给小白图示讲解OFDM 下面以图示为主讲解OFDM,以"易懂"为第一要义. 注:下面的讨论如果不做说明,均假设为理想信道. *** 一张原理 ...
- Week2——提交表单后后台的工作
在我理解看来,发生请求后主要是通过域进行相互间的协调作用的.表单数据可以从request域中获得,也可以通过response域返回数据给前台. 当发起http请求后,已经启动的Tomcat服务器解析收 ...
- .NET的那些事儿(9)——C# 2.0 中用iTextSharp制作PDF(基础篇) .
该文主要介绍如何借助iTextSharp在C# 2.0中制作PDF文件,本文的架构大致按照iTextSharp的操作文档进行翻译,如果需要查看原文,请点击一下链接:http://itextsharp. ...
- http状态码汇总及问题经验总结
我们经常会遇到404.500.302等提示,它们究竟是什么意思呢?除了这几个常见的状态码外,还有哪些我们没有遇到过的但有可能出现的状态码呢?这里本人做了一个汇总,与大家分享一下. 常见的HTTP错误可 ...
- 错误:该表单无法显示,可能是由于 Microsoft SharePoint Server State Service 配置不当。有关详细信息,请与服务器管理员联系
问题场景: 1.SharePoint 2013 中工作流需要状态服务(State Service),如果没有正确配置状态服务,则在给列表.文档库添加工作流时会遇到错误: “该表单无法显示,可能是由于 ...
- python 网络编程 -- Tcp协议
Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 客户端 大多数连接都是可靠 ...
- SQL Server系统常用存储过程
SQL Server系统存储过程也是好几百个,算了,还是写几个常用的. 1.sp_help 查询表的信息 执行存储过程: sp_help Person 显示结果如下: 妈了个B,有了这张图,你还不懂怎 ...