当前位置:网站首页>代码分析Objective-C中的深拷贝与浅拷贝
代码分析Objective-C中的深拷贝与浅拷贝
2022-08-03 10:58:00 【阿腾木】
oc这门语言属于奇葩中的奇葩,基本类型的对象分为“可变”类型与“不可变”类型。
比如下面这些类型
可变 | 不可变 |
---|---|
NSArray | NSMutableArray |
NSString | NSMutableString |
NSNumber | NSMutableNumber |
… | … |
可变类型可以看作是“变量”,不可变类型可以看作是“常量”。当然,只是表面上比较像。
两种类型都是NSObject
的子类,都实现了NSObject
中的mutableCopy
与copy
方法。
有关这两种方法,Apple是这样介绍的:
在oc中 copy和mutableCopy两个方法是被所有对象(继承自NSObject的类)继承的,这两个方法就是为copy准备的。其中,mutableCopy是为了创建原始对象的可变类型的copy。这两个方法分别调用copyWithZone和mutableCopyWithZone两个方法来进行copy。一个类必须实现copyWithZone或者mutableCopyWithZone,才能进行copy或者mutableCopy。
两种类型(可变、不可变),两种方法(mutableCopy、copy),就产生了四种组合:
- 可变类型调用copy
- 可变类型调用mutableCopy
- 不可变类型调用copy
- 不可变类型调用mutableCopy
这四种组合衍生出了两种概念,浅拷贝
与深拷贝
:
- 浅copy: 指针复制,不会创建一个新的对象。
- 深copy: 内容复制,会创建一个新的对象。
概念太空,用代码来理解:
#import <Foundation/Foundation.h>
int main(int args, const char *argv[]) {
@autoreleasepool {
// 可变对象调用copy,mutableCopy
NSMutableString *mutableString1 = [[NSMutableString alloc] init];
[mutableString1 setString:@"hello1"];
id s1 = mutableString1.copy;
id s2 = mutableString1.mutableCopy;
NSLog(@"可变对象:%p %@", mutableString1,mutableString1.class);
NSLog(@"调用copy:%p %@", s1, [s1 class]);
NSLog(@"调用mutableCopy:%p %@ \n\n", s2, [s2 class]);
// 可变对象调用copy,mutableCopy
NSString *immutableString1 = @"hello2";
id s3 = immutableString1.copy;
id s4 = immutableString1.mutableCopy;
NSLog(@"不可变对象:%p %@", immutableString1,immutableString1.class);
NSLog(@"调用copy:%p %@", s3, [s3 class]);
NSLog(@"调用mutableCopy:%p %@", s4, [s4 class]);
}
return 0;
}
以第一部分“可变对象调用copy,mutableCopy”为例
先创建一个可变对象,然后为其设置一个值“hello1”
NSMutableString *mutableString1 = [[NSMutableString alloc] init];
[mutableString1 setString:@"hello1"];
因为我们不知道copy
与mutableCopy
返回的对象具体是什么类型的,因此我们用两个id
变量来获取
id s1 = mutableString1.copy;
id s2 = mutableString1.mutableCopy;
%p
可以打印出指针的值,[s1 class]
可以知道是哪个类,因此可以打印出原变量、copy对象和mutableCopy对象的内存地址与类型,如下。
NSLog(@"可变对象:%p %@", mutableString1,mutableString1.class);
NSLog(@"调用copy:%p %@", s1, [s1 class]);
NSLog(@"调用mutableCopy:%p %@ \n\n", s2, [s2 class]);
打印结果如下(省略无关部分):
可变对象:0x600003058ba0 __NSCFString
调用copy:0xaf10ee324c733912 NSTaggedPointerString
调用mutableCopy:0x600003058bd0 __NSCFString
可以看出,三个内存地址都是不一样的,说明产生了新的对象,因此
可变类型调用copy与mutableCopy都是深拷贝
再看一下不可变部分的代码
NSString *immutableString1 = @"hello2";
id s3 = immutableString1.copy;
id s4 = immutableString1.mutableCopy;
NSLog(@"不可变对象:%p %@", immutableString1,immutableString1.class);
NSLog(@"调用copy:%p %@", s3, [s3 class]);
NSLog(@"调用mutableCopy:%p %@", s4, [s4 class]);
与之前的代码基本类似,直接看输出:
不可变对象:0x100ce40e8 __NSCFConstantString
调用copy:0x100ce40e8 __NSCFConstantString
调用mutableCopy:0x600001980cc0 __NSCFString
可以看出:
- 不可变对象调用copy:浅拷贝
- 不可变对象调用mutableCopy:深拷贝
一句话总结:
只有不可变对象调用copy是浅拷贝,其他都是深拷贝
有关copy的深度长文:https://www.jianshu.com/p/5f776a4816ee
边栏推荐
猜你喜欢
[Star Project] Little Hat Plane Battle (9)
玉溪卷烟厂通过正确选择时序数据库 轻松应对超万亿行数据
How to retrieve IDC research reports?
QT with OpenGL(HDR)
Machine Learning Overview
巴比特 | 元宇宙每日必读:玩家离场,平台关停,数字藏品市场正逐渐降温,行业的未来究竟在哪里?...
What is the relationship between The Matrix and 6G?
MySQL数据库实战(1)
全新的Uber App设计
Dry goods!A highly structured and sparse linear transformation called Deformable Butterfly (DeBut)
随机推荐
增加WebView对localStorage的支持
【TypeScript】Why choose TypeScript?
C#/VB.NET 从PDF中提取表格
redis基础知识总结——数据类型(字符串,列表,集合,哈希,集合)
SAP 电商云 Spartacus UI 的 External Routes 设计明细
Boolean 与numeric 无法互转
2022年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多
numpy
LP流动性挖矿DAPP系统开发丨流动性挖矿功能原理及说明
Machine Learning Overview
科普大佬说 | 黑客帝国与6G有什么关系?
【无标题】函数,对象,方法的区别
机器学习(公式推导与代码实现)--sklearn机器学习库
智能合约是什么?
[华为云在线课程][SQL语法入门][学习笔记]
白帽黑客与留守儿童破壁对“画”!ISC、中国光华科技基金会、光明网携手启动数字安全元宇宙公益展
【二分查找详解外加递归写法】附有全部代码
完全背包问题的思路解析
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之二
type="module" you know, but type="importmap" you know