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"; ...
随机推荐
- ajax异步上传图片三种方案
转自:http://www.jb51.net/article/51180.htm 注:自己尝试了前两种,都可用: 目前常用的异步文件上传功能有几种,比较多见的如使用iframe框架形式,ajax功能效 ...
- 什么是首字节时间(TTFB)
第一字节响应时间(TTFB)=从发送请求到WEB服务器的时间+WEB服务器处理请求并生成响应花费的时间+WEB服务器生成响应到浏览器花费的时间测量第一字节响应时间(TTFB)的工具:http://ww ...
- Node.js 的安装
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 的运行环境,简单的说就是运行在服务端的 JavaScript.所以学起来还是比较容易接受的. Node.js 使用事件驱动 ...
- CentOS 7 Apache 多端口部署 Web Apps 指南
转载自简书,原作者xuyan0,链接https://www.jianshu.com/p/b34c78bf9bf0,如有侵权,请联系删除 导语 Apache web 服务器运行着互联网上超过半数的活跃的 ...
- SVN的正确提交方式
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Rundy_Deng/article/details/80338093 也会让我们百思不得其解,甚至耽 ...
- 从golang-gin-realworld-example-app项目学写httpapi (一)
https://wangzitian0.github.io/2013/06/29/zero-to-one-1/ https://github.com/gothinkster/golang-gin-re ...
- 打通版微社区(6):部署微信插件及开通QQ云服务
写在前面: 此文是我最后写的.其实实际部署的时候,我是先安装了论坛并试图开通微信的微社区.发现微社区需要在微信公众平台的开发者中心里配置 "网页账号,网页授权获取用户基本信息"为论 ...
- cmd命令提示符大全(干货)
cmd是command的缩写.即命令提示符(CMD),是在OS / 2 , Windows CE与Windows NT平台为基础的操作系统(包括Windows 2000和XP中, Vista中,和Se ...
- 沉淀再出发:使用python进行机器学习
沉淀再出发:使用python进行机器学习 一.前言 使用python进行学习运算和机器学习是非常方便的,因为其中有很多的库函数可以使用,同样的python自身语言的特点也非常利于程序的编写和使用. 二 ...
- 二进制安装mariaDB
1.获取二进制安装包 获取二进制格式MariaDB安装包,可去官网下载. 因为是实验环境,所以选择了最新版. mariadb-10.2.12-linux-x86_64.tar.gz 2.解压 解压到 ...