OC语言 - 内存管理:字符串 | 容器 | 点语法

字符串

1 - 在使用 NSString、NSDate...等轻量数据类型时,它们的引用计数有时会受到 Tagged Pointer 影响,但这并不会影响内存管理原则

 1     // 常量区字符串无须管理内存,于 retain/release 操作无关
 2     NSString *strA = @"妇好";
 3     [strA retain];
 4     [strA retain];[strA retain];[strA retain];
 5     NSLog(@"%lu",[strA retainCount]);// 18446744073709551615
 6 
 7     
 8     // 因 Tagged Pointer 有时创建的字符串对象并不在堆区:只要存储的数据有点大,就会跑到堆区
 9     NSString *strB = [[NSString alloc] initWithFormat:@"你不是我,怎么知道我不快乐!我不是你,但是我知道你并不快乐!后面省略一万字"];
10     [strB retain];
11     NSLog(@"%lu",[strB retainCount]);// 2
12     [strB release];// 只要看到 alloc、retain、copy/mutableCopy 就要有与之对应的 release,不须关心在它在内存中如何分配
13     NSLog(@"%lu",[strB retainCount]);// 1
14     [strB release];
15 
16 
17     // 便利构造器自带有 autorelease,无需手动 release
18     NSString *str12 = [NSString stringWithFormat:@"花花世界"];
19     NSLog(@"%lu",[str12 retainCount]);// 1

容器

1 - 容器会影响其所管理对象的引用计数,下面我们以数组为例

 1     NSArray *arrayA = [[NSArray alloc] initWithObjects:@"1", nil];// 1          被管理对象
 2     NSMutableArray *arrayB = [[NSMutableArray alloc] initWithCapacity:1];// 1   管理者
 3     
 4     // 谁污染谁治理原则
 5     [arrayA retain];// 2
 6     [arrayA retain];// 3
 7     [arrayA retain];// 4
 8     [arrayA retain];// 目前 arrayA 引用计数是 5
 9     
10     printf("------------------添加------------------\n");
11      // 对于容器,当把对象添加进数组一次,被管理对象的引用计数就 +1一次
12     [arrayB addObject:arrayA];
13     NSLog(@"%lu",[arrayA retainCount]);// 6
14     [arrayB addObject:arrayA];
15     NSLog(@"%lu",[arrayA retainCount]);// 7
16     [arrayB addObject:arrayA];
17     NSLog(@"%lu",[arrayA retainCount]);// 8
18     [arrayB addObject:arrayA];
19     NSLog(@"%lu",[arrayA retainCount]);// 9
20     
21     
22     printf("\n------------------移除----------------\n");
23     [arrayB removeLastObject]; // -1
24     NSLog(@"%lu",[arrayA retainCount]);// 8
25     [arrayB removeLastObject];
26     NSLog(@"%lu",[arrayA retainCount]);// 7
27 
28     // 当移除某个对象,则引用计数会还原到起始值(arrayA 被添加进容器 arrayB 之前时的计数)
29     [arrayB removeObject:arrayA];
30     NSLog(@"%lu",[arrayA retainCount]);// 5
31     // 添加
32     [arrayB addObject:arrayA];
33     NSLog(@"%lu",[arrayA retainCount]);// 6
34 
35 
36     printf("\n-------------对容器进行 retain、release------------\n");
37     // 注:在容器没销毁前,对容器本身进行 retain、release 操作,被管理对象的引用计数并不会受到影响
38     [arrayB retain];// 2
39     NSLog(@"%lu",[arrayA retainCount]);// arrayA 依旧是 6
40     [arrayB release];// 1
41     NSLog(@"%lu",[arrayA retainCount]);// arrayA 依旧是 6
42     [arrayB addObject:arrayA];// 7
43 
44     
45     printf("\n-----------------移除某个对象------------------\n");
46     
47     [arrayB removeObject:arrayA];
48     NSLog(@"%ld",arrayA.retainCount);// 从 7 变成 5
49 
50 
51     printf("\n-------------容器销毁或移除所有对象-------------\n");
52     [arrayA retain];// 6
53     [arrayB addObject:arrayA];// 7
54     [arrayB addObject:arrayA];// 8
55 
56     // 当容器销毁或移除所有对象时,对象的引用计数还原到起始值
57     [arrayB removeAllObjects];
58     NSLog(@"移除所有对象:%lu",[arrayA retainCount]);// 6
59     
60     [arrayB addObject:arrayA];// 7
61     [arrayB addObject:arrayA];// 8
62     [arrayB release];// 0
63     NSLog(@"容器已销毁:%lu",[arrayA retainCount]);// 6

点语法

1 - 点语法是否会影响对象引用计数的变化,决定性因素是看属性所使用何种语义特性

// - Student.h

1 #import <Foundation/Foundation.h>
2 @interface Student : NSObject
3 
4 @property (nonatomic,retain)NSString *name;
5 @property (nonatomic,retain)NSArray *array;
6 
7 - (void)printArray;
8 
9 @end

// - Student.m

 1 #import "Student.h"
 2 @implementation Student
 3 
 4 -(void)dealloc{
 5 
 6     self.name = nil;
 7     self.array = nil;
 8     [super dealloc];
 9 }
10 
11 - (NSString *)name{
12 
13     return [[_name retain] autorelease];// 本质是为了延长对象的生命周期
14 }
15 
16 - (void)printArray{
17 
18     
19     self.array = [[NSArray alloc] initWithObjects:@"1",@"2", nil];
20     NSLog(@"%lu",[_array retainCount]);// 2
21 
22     // 在方法里边创建的对象:在出方法前一定要记得 release 或者 autorelease
23     [[_array autorelease] autorelease];
24     [self textContent];
25 }
26 
27 - (void)textContent{
28     
29     NSLog(@"出了方法后的引用计数:%lu",[_array retainCount]);// 2:因为使用的是 autorelease,所以依旧是 2(实际上系统会帮你销毁,我们无需管理)
30 }
31 
32 @end

// - main

 1 #import <Foundation/Foundation.h>
 2 #import "Student.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5 
 6     Student *stu11 = [[Student alloc] init];
 7     [stu11 printArray];
 8     [stu11 release];
 9 
10     return 0;
11 }

 

posted on 2018-09-11 14:38  低头捡石頭  阅读(38)  评论(0编辑  收藏  举报

导航