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"; ...
随机推荐
- 新手嘛,先学习下 Vue2.0 新手入门 — 从环境搭建到发布
Vue2.0 新手入门 — 从环境搭建到发布 转自:http://www.runoob.com/w3cnote/vue2-start-coding.html 具体文章详细就不搬了,步骤可过去看,我这就 ...
- Monte Calro Tree Search (MCTS)
https://blog.csdn.net/natsu1211/article/details/50986810, 感谢分享! Intro最近阿法狗和李师师的人机大战着实火了一把,还顺带捧红了柯杰,古 ...
- 搭建高可用mongodb集群(三)—— 深入副本集内部机制
在上一篇文章<搭建高可用mongodb集群(二)-- 副本集> 介绍了副本集的配置,这篇文章深入研究一下副本集的内部机制.还是带着副本集的问题来看吧! 副本集故障转移,主节点是如何选举的? ...
- centos7安装lua语言环境
Linux 上安装 Lua 安装非常简单,只需要下载源码包并在终端解压编译即可. 官网地址:http://www.lua.org/download.html 我这里安装的是:lua-5.3.0.tar ...
- c# 控制台定时程序
using System; using System.Timers; namespace DaoChuCore2 { class Program { static void Main(string[] ...
- SQL 语句及关键字的用法
一.SELECT select [ALL|DISTINCT] select_list [into new table] FROM table_source [where serch_conditaio ...
- CAMediaTimingFunction的使用
CAMediaTimingFunction的使用 CAMediaTimingFunction可以用在POP动画的自定义动画当中,算是非常实用的工具,当然,系统的动画也是可以使用的. 效果: 需要用到的 ...
- MTK 官方 openwrt SDK 使用
来源 1.https://github.com/unigent/openwrt-3.10.14 上面有个 问题:SDK 缺少 linux-3.10.14-p112871.tar.xz 在 http ...
- 41、Thead线程 System.Thread与互斥体Mutex
Thead线程 System.Thread 使用Thread类可以创建和控制线程.下面的代码是创建和启动一个新线程的简单例子.Thread 类的构造函数重载为接受ThreadStart和Paramet ...
- 如果要遍历除了for循环,你还知道什么?——JavaScript的各种遍历方式
如果要遍历除了for循环,你还知道什么?——JavaScript的各种遍历方式 这是曾经面试中的一道题目,当时的我用现在很潮的话讲,整个人是懵比的,我呆呆的说了句,我好像只知道for循环啊.后来回过神 ...