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:@"33"];
    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

原文地址:https://www.cnblogs.com/lisaloveyou1900/p/10464878.html

时间: 2024-10-10 01:36:18

Objective-C 之深拷贝和浅拷贝的相关文章

【转载】C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #include <iostream>using namespace std;class CExample {private:     int a;public:     CExample(int b)     { a=b;}     void Show ()     {        cout<

完全理解python深拷贝和浅拷贝

import copya = [1, 2, 3, 4, ['a', 'b']]  #原始对象b = a  #赋值,传对象的引用c = copy.copy(a)  #对象拷贝,浅拷贝d = copy.deepcopy(a)  #对象拷贝,深拷贝a.append(5)  #修改对象aa[4].append('c')  #修改对象a中的['a', 'b']数组对象print 'a = ', aprint 'b = ', bprint 'c = ', cprint 'd = ', d 输出结果:a = 

javaScript之深拷贝与浅拷贝

js中有两种数据类型: 1.  基本类型  :  Number.String.Boolean.Null.Undefined 2.  复杂类型  :  Object .Array 深拷贝和浅拷贝只针对复杂类型的数据,因为基本类型数据的定义都会重新开辟新的内存. 浅拷贝拷贝的是内存地址,只是增加一个指针指向已有的内存,这时多个数据共用一个内存空间:深拷贝是新增了指针并且新开辟了内存空间,新指针指向新的内存. 浅拷贝: var a={ name:'WangJing', sex:'女', age:'25

C++拷贝构造函数(深拷贝,浅拷贝)

http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 #include <iostream> 2 using namespace std; 3 4 class CExample { 5 private: 6 int a; 7 public: 8

python 中 深拷贝和浅拷贝的理解

在总结 python 对象和引用的时候,想到其实 对于python的深拷贝和浅拷贝也可以很好对其的进行理解. 在python中,对象的赋值的其实就是对象的引用.也就是说,当创建一个对象,然后赋给另外一个变量之后,实际上只是拷贝了这个对象的引用. 我们先用  利用切片操作和工厂方法list方法 来阐述一下浅拷贝. 举个栗子: Tom = ['Tom', ['age', 10]] Jack = Tom[:] ……切片操作 June = list(Tom) 接下来查看一下 上述三个变量的引用: >>

实现CMyString类--深拷贝与浅拷贝

实现CMyString类,实现赋值运算符函数(深拷贝与浅拷贝(写时拷贝)) 深拷贝:赋值运算符函数说明 步骤1.释放原来的内存空间 步骤2.再重新开辟要赋值的对象的大小的空间 步骤3.再将另一个对象的值拷贝给this对象 友元函数的说明:由于输出重载需要俩个参数,不能再隐含this指针,故使用友元函数 代码如下: <span style="font-size:18px;">class CMyString { public: CMyString() :str(new char

python 深拷贝和浅拷贝之可变和不可变对象总结

了解深拷贝和浅拷贝之前先要理解可变与不可变对象 python只允许使用引用传递,有可变对象和不可变对象,可变对象:list,dict.不可变对象有:int,string,float,tuple Python int,string,float,tuple不可变举栗子: def int_object(): i = 89 j = 89 print(id(89)) print('i id:' + str(id(i))) print('j id:' + str(id(j))) print(i is j)

深拷贝与浅拷贝

一.浅拷贝和深拷贝 所谓浅拷贝,就是由默认的拷贝构造函数所实现的对数据成员逐一赋值.若类中含有指针类型的数据,这种方式只是简单的把指针的指向赋值给新成员,但并没有给新成员分配内存,因此这种方式必然会导致错误.为了解决浅拷贝出现的错误,必须显示的定义一个拷贝构造函数,使之不但复制数据成员,而且为对象分配各自的内存空间,这就是所谓的深拷贝. 二.浅拷贝 浅拷贝就是由默认的拷贝构造函数所实现的数据成员逐一赋值.通常默认的拷贝构造函数能够胜任这个工作,但是若类中含有指针类型的数据,这种数据成员逐一赋值的

【转】 C++的深拷贝与浅拷贝

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> using namespace std; class CExample { private:      int a; public:      CE

python 深拷贝与浅拷贝

浅拷贝的方式有: lst=[1,2,3] (1)直接赋值: lst_cp = lst (2)for循环遍历生成:lst_cp= [i for i in lst] (3)copy模块下,copy.copy仍为浅拷贝 深拷贝的方式 (1)借助copy模块 >>> import copy >>> lst_cp = copy.deepcopy(lst) 以上方法的测试: 注意:因为string类型是不可变类型,所以修改string元素时会新创建一个地址空间放置数据 (1)直接赋