iOS - 深拷贝、浅拷贝探索验证

778 阅读4分钟

本文已同步简书:iOS - 深拷贝、浅拷贝探索验证

1. 概念

浅拷贝: 拷贝后,并没有进行真正的复制,拷贝后对象和原对象指向同一个地址

深拷贝: 拷贝后对象指向了新的地址

2. 非集合类对象

  1. ####非集合类不可变对象
    NSString *str1 = @"hello world";
    NSString *str2 = [str1 copy];
    NSString *str3 = [str1 mutableCopy];
    
    NSLog(@"\n str1 = %p class = %@", str1, str1.class);
    NSLog(@"\n str2 = %p class = %@", str2, str2.class);
    NSLog(@"\n str3 = %p class = %@", str3, str3.class);

输出

2021-05-08 17:09:47.697211+0800 AlgorithmDemo[33483:14523594] 
 str1 = 0x100008220 class = __NSCFConstantString
 str2 = 0x100008220 class = __NSCFConstantString
 str3 = 0x10044f8d0 class = __NSCFString

由打印可得:

  • 对于非集合类不可变对象的copy为浅拷贝,mutableCopy为深拷贝
  • 浅拷贝获得的对象与原对象地址一致,返回的对象为不可变对象(其实就是原对象)
  • 深拷贝返回新的内存地址,返回的对象为可变对象

####2. 非集合类可变对象

    NSString *str1 = [NSMutableString stringWithString:@"hello world"];
    NSMutableString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    
    NSLog(@"\n str1 = %p class = %@", str1, str1.class);
    NSLog(@"\n str2 = %p class = %@", str2, str2.class);
    NSLog(@"\n str3 = %p class = %@", str3, str3.class);

输出

2021-05-08 17:10:45.047818+0800 AlgorithmDemo[33588:14525427] 
 str1 = 0x1029045f0 class = __NSCFString
 str2 = 0x102904640 class = __NSCFString
 str3 = 0x102904760 class = __NSCFString

由打印可得

  • 非集合类可变对象copy是深拷贝
  • 非集合类可变对象mutableCopy是深拷贝
  • copy和mutableCopy返回的对象都是可变对象

3. 集合类对象

集合类不可变对象

    NSString *str1 = @"hello world";
    NSMutableString *str2 = [NSMutableString stringWithString:@"hello world"];
    NSArray *array1 = [NSArray arrayWithObjects: str1, str2, nil];
    NSArray *array2 = [array1 copy];
    NSArray *array3 = [array1 mutableCopy];
    
    NSLog(@"\n array1 = %p class = %@ \n", array1, [array1 class]);
    NSLog(@"\n array2 = %p class = %@ \n", array2, [array2 class]);
    NSLog(@"\n array3 = %p class = %@ \n", array3, [array3 class]);
    
    NSLog(@"\n\n======== 元素是String ======== ");
    NSLog(@"\n obj0 = %p class = %@ \n", array1[0], [array1[0] class]);
    NSLog(@"\n obj0 = %p class = %@ \n", array2[0], [array2[0] class]);
    NSLog(@"\n obj0 = %p class = %@ \n", array3[0], [array3[0] class]);
   
    NSLog(@"\n\n======== 元素是mutableString ========");
    NSLog(@"\n obj1 = %p class = %@ \n", array1[1], [array1[1] class]);
    NSLog(@"\n obj1 = %p class = %@ \n", array2[1], [array2[1] class]);
    NSLog(@"\n obj1 = %p class = %@ \n", array3[1], [array3[1] class]);

输出

2021-05-08 17:34:32.740896+0800 AlgorithmDemo[39309:14557776] 
 array1 = 0x102904180 class = __NSArrayI
 array2 = 0x102904180 class = __NSArrayI
 array3 = 0x102904260 class = __NSArrayM

======== 元素是String ======== 
 obj0 = 0x100008220 class = __NSCFConstantString
 obj0 = 0x100008220 class = __NSCFConstantString
 obj0 = 0x100008220 class = __NSCFConstantString

======== 元素是mutableString ========
 obj1 = 0x1028719b0 class = __NSCFString
 obj1 = 0x1028719b0 class = __NSCFString
 obj1 = 0x1028719b0 class = __NSCFString

由打印可得:

  • 集合类不可变对象的copy为浅拷贝
  • mutableCopy为深拷贝
  • 无论copy还是mutableCopy集合内元素都是浅拷贝

集合类可变对象

    NSString *str1 = @"hello world";
    NSMutableString *str2 = [NSMutableString stringWithString:@"hello world"];
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects: str1, str2, nil];
    NSMutableArray *array2 = [array1 copy];
    NSMutableArray *array3 = [array1 mutableCopy];
    
    NSLog(@"\n array1 = %p class = %@ \n", array1, [array1 class]);
    NSLog(@"\n array2 = %p class = %@ \n", array2, [array2 class]);
    NSLog(@"\n array3 = %p class = %@ \n", array3, [array3 class]);
    
    NSLog(@"\n\n======== 元素是mutableString ========");
    NSLog(@"\n obj0 = %p class = %@ \n", array1[0], [array1[0] class]);
    NSLog(@"\n obj0 = %p class = %@ \n", array2[0], [array2[0] class]);
    NSLog(@"\n obj0 = %p class = %@ \n", array3[0], [array3[0] class]);
    
    
    NSLog(@"\n\n======== 元素是String ======== ");
    NSLog(@"\n obj1 = %p class = %@ \n", array1[1], [array1[1] class]);
    NSLog(@"\n obj1 = %p class = %@ \n", array2[1], [array2[1] class]);
    NSLog(@"\n obj1 = %p class = %@ \n", array3[1], [array3[1] class]);

输出:

2021-05-08 17:40:01.757406+0800 AlgorithmDemo[40202:14563979] 
 array1 = 0x1006046e0 class = __NSArrayM
 array2 = 0x100604860 class = __NSArrayI
 array3 = 0x100604890 class = __NSArrayM

======== 元素是mutableString ========
 obj0 = 0x100008220 class = __NSCFConstantString
 obj0 = 0x100008220 class = __NSCFConstantString
 obj0 = 0x100008220 class = __NSCFConstantString

======== 元素是String ======== 
 obj1 = 0x100604510 class = __NSCFString
 obj1 = 0x100604510 class = __NSCFString
 obj1 = 0x100604510 class = __NSCFString

结论: 集合类可变对象的mutableCopy和copy都是深拷贝,但集合内元素是浅拷贝

总结

列个表看看 非集合类

_copymutableCopy
NSString浅拷贝返回原对象深拷贝返回新的NSString
NSMutableString深拷贝返回新NSMutableString深拷贝 返回新NSMutableString

一句话总结:非集合类对象只有不可变对象的copy是浅拷贝,其它都是深拷贝 集合类

_copymutableCopy
NSArray浅拷贝元素浅拷贝深拷贝元素浅拷贝
NSMutableArray深拷贝元素浅拷贝深拷贝元素浅拷贝

一句话总结:集合类对象只有不可变对象的copy是浅拷贝,其它都是深拷贝,且集合内元素都是浅拷贝

也可换个方式总结:

  • copy: 对不可变对象是浅拷贝,可变对象是深拷贝
  • mutableCopy: 始终是深拷贝
  • 无论深浅拷贝,集合对象内元素都是浅拷贝