iOS深拷贝与浅拷贝、NSString内存分配

copy与retain的区别

         1)copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。Copy属性表示两个对象内容相同,新的对象retain为1 ,与旧有对象的引用计数无关,旧有对象没有变化。copy减少对象对上下文的依赖。

         2)retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1也就是说,retain 是指针拷贝,copy 是内容拷贝。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#pragma mark - iOS系统的集合类与非集合类的retain和copy
        // 非容器类(NSString / NSNumber等)
        NSString *str1 = [[NSString alloc] initWithFormat:@"%@", @"Jacedy"];
        NSString *str11 = [str1 retain];
        NSString *str12 = [str1 copy];
        NSString *str13 = [str1 mutableCopy];
         
        NSMutableString *str2 = [[NSMutableString alloc] initWithString:@"Jake"];
        NSMutableString *str21 = [str2 retain];
        NSMutableString *str22 = [str2 copy];
        NSMutableString *str23 = [str2 mutableCopy];
         
        NSLog(@"非容器类");
        NSLog(@"str1 的地址:%p,retainCount:%lu", str1, (unsigned long)[str1 retainCount]);
        NSLog(@"str11的地址:%p,retainCount:%lu", str11, (unsigned long)[str11 retainCount]);
        NSLog(@"str12的地址:%p,retainCount:%lu", str12, (unsigned long)[str12 retainCount]);
        NSLog(@"str13的地址:%p,retainCount:%lu\n\n", str13, (unsigned long)[str13 retainCount]);
        NSLog(@"str2 的地址:%p,retainCount:%lu", str2, (unsigned long)[str2 retainCount]);
        NSLog(@"str21的地址:%p,retainCount:%lu", str21, (unsigned long)[str21 retainCount]);
        NSLog(@"str22的地址:%p,retainCount:%lu", str22, (unsigned long)[str22 retainCount]);
        NSLog(@"str23的地址:%p,retainCount:%lu\n\n", str23, (unsigned long)[str23 retainCount]);
         
        // 容器类(集合类)(NSArray / NSSet等)
        NSArray *arr1 = [NSArray arrayWithObjects:@"one", @"two", nil];
        NSArray *arr11 = [arr1 retain];
        NSArray *arr12 = [arr1 copy];
        NSArray *arr13 = [arr1 mutableCopy];
         
        NSMutableArray *arr2 = [NSMutableArray arrayWithObjects:@"one", @"two", nil];
        NSMutableArray *arr21 = [arr2 retain];
        NSMutableArray *arr22 = [arr2 copy];
        NSMutableArray *arr23 = [arr2 mutableCopy];
         
        NSLog(@"容器类");
        NSLog(@"arr1 的地址:%p,retainCount:%lu", arr1, (unsigned long)[arr1 retainCount]);
        NSLog(@"arr11的地址:%p,retainCount:%lu", arr11, (unsigned long)[arr11 retainCount]);
        NSLog(@"arr12的地址:%p,retainCount:%lu", arr12, (unsigned long)[arr12 retainCount]);
        NSLog(@"arr13的地址:%p,retainCount:%lu", arr13, (unsigned long)[arr13 retainCount]);
        NSLog(@"arr1[0] :%p", arr1[0]);
        NSLog(@"arr13[0]:%p\n\n", arr13[0]);
         
        NSLog(@"arr2 的地址:%p,retainCount:%lu", arr2, (unsigned long)[arr2 retainCount]);
        NSLog(@"arr21的地址:%p,retainCount:%lu", arr21, (unsigned long)[arr21 retainCount]);
        NSLog(@"arr22的地址:%p,retainCount:%lu", arr22, (unsigned long)[arr22 retainCount]);
        NSLog(@"arr23的地址:%p,retainCount:%lu", arr23, (unsigned long)[arr23 retainCount]);
        NSLog(@"arr2[0] :%p", arr2[0]);
        NSLog(@"arr22[0]:%p\n\n", arr22[0]);
         
#pragma mark - NSString 内存管理
         
        NSString *string1 = @"Jacedy";
        NSString *string2 = [[NSString alloc] initWithString:@"KJacedy"];
        NSString *string3 = [[NSString alloc] initWithFormat:@"Jacedy"];
        NSString *string4 = [NSString stringWithFormat:@"K-Jacedy"];
        //NSString *string5 = [NSString stringWithString:@"Jacedy"];    //该方法等同于string1
        NSLog(@"NSString内存管理");
        NSLog(@"string1:%p retainCount:%lu  class:%@", string1, [string1 retainCount], [string1 class]);
        NSLog(@"string2:%p retainCount:%lu  class:%@", string2, [string2 retainCount], [string2 class]);
        NSLog(@"string3:%p retainCount:%lu  class:%@", string3, [string3 retainCount], [string3 class]);
        NSLog(@"string4:%p retainCount:%lu  class:%@\n\n", string4, [string4 retainCount], [string4 class]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 输出结果:
 
非容器类
str1 的地址:0x79646563614a65,retainCount:18446744073709551615
str11的地址:0x79646563614a65,retainCount:18446744073709551615
str12的地址:0x79646563614a65,retainCount:18446744073709551615
str13的地址:0x100203a70,retainCount:1
 
str2 的地址:0x100203f20,retainCount:2
str21的地址:0x100203f20,retainCount:2
str22的地址:0x656b614a45,retainCount:18446744073709551615
str23的地址:0x100204040,retainCount:1
 
容器类
arr1 的地址:0x100300a90,retainCount:3
arr11的地址:0x100300a90,retainCount:3
arr12的地址:0x100300a90,retainCount:3
arr13的地址:0x100301190,retainCount:1
arr1[0] :0x1000021b0
arr13[0]:0x1000021b0
 
arr2 的地址:0x100301260,retainCount:2
arr21的地址:0x100301260,retainCount:2
arr22的地址:0x100301370,retainCount:1
arr23的地址:0x100301390,retainCount:1
arr2[0] :0x1000021b0
arr22[0]:0x1000021b0
 
NSString内存管理
string1:0x100002050 retainCount:18446744073709551615  class:__NSCFConstantString
string2:0x100002390 retainCount:18446744073709551615  class:__NSCFConstantString
string3:0x79646563614a65 retainCount:18446744073709551615  class:NSTaggedPointerString
string4:0xd2eec83802a585 retainCount:18446744073709551615  class:NSTaggedPointerString
 
Program ended with exit code: 0

深拷贝与浅拷贝结论

         1)对非集合类:

         [immutableObject copy] // 浅复制

         [immutableObject mutableCopy] //深复制

         [mutableObject copy] //深复制

         [mutableObject mutableCopy] //深复制

         

         2)对集合类:

         [immutableObject copy] // 浅复制

         [immutableObject mutableCopy] //单层深复制(即仅对对象本身进行深复制,对象元素仍是浅复制(指针拷贝,内存地址不变))

         [mutableObject copy] //单层深复制

         [mutableObject mutableCopy] //单层深复制

         

NSString内存分配结论

         @“” 和 initWithString:方法生成的字符串分配在常量区,系统自动管理内存;

         initWithFormat:和 stringWithFormat: 方法生成的字符串分配在堆区,autorelease


上一篇:转 iOS应用程序的状态及其切换(生命周期)


下一篇:分享实录 | 深度学习技术红利下的代码补全