学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

NSString内存管理

一道面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@interface ViewController : UIViewController
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, weak) NSString *string2;
@end


@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.

[self testKeyword];
}

-(void)testKeyword {
self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 1 = %@",self.string1);
NSLog(@"String 2 = %@", self.string2);
}
@end

NSString内存管理

NSStringOC的内存管理策略中是一个特殊的存在,因为其在编译和运行中做了一些优化处理。

1
2
3
4
5
6
7
8
9
10
11
12
//宏定义
#define XWLog(_var) ({ NSString *name = @#_var; NSLog(@"变量名=%@,类型=%@, 地址=%p,值=%@,引用计数=%d", name, [_var class], _var, _var, (int)[_var retainCount]); })

//测试代码
NSString *a = @"string";
NSString *b = [[NSString alloc]init];
NSString *c = [[NSString alloc]initWithString:@"string"];
NSString *d = [[NSString alloc]initWithFormat:@"string"];
NSString *e = [NSString stringWithFormat:@"string"];
NSString *f = [NSString stringWithFormat:@"123456789"];
NSString *g = [NSString stringWithFormat:@"1234567890"];
XWLog(a); XWLog(b); XWLog(c); XWLog(d); XWLog(e); XWLog(f); XWLog(g);
1
2
3
4
5
6
7
8
//打印结果
变量名=a,类型=__NSCFConstantString, 地址=0x1015f3120,值=string,引用计数=-1
变量名=b,类型=__NSCFConstantString, 地址=0x1019808d0,值=,引用计数=-1
变量名=c,类型=__NSCFConstantString, 地址=0x1015f3120,值=string,引用计数=-1
变量名=d,类型=NSTaggedPointerString, 地址=0xa00676e697274736,值=string,引用计数=-1
变量名=e,类型=NSTaggedPointerString, 地址=0xa00676e697274736,值=string,引用计数=-1
变量名=f,类型=NSTaggedPointerString, 地址=0xa1ea1f72bb30ab19,值=123456789,引用计数=-1
变量名=g,类型=__NSCFString, 地址=0x60800002b580,值=1234567890,引用计数=1

__NSCFString

对象类型的字符串,在运行时创建,存储在堆区,服从OC的对象内存管理策略,长度不能太小(内容若包含中文字符,不论长度大小,都是NSCFString),否则创建的是NSTaggedPointerString类型,例如上面f与g

NSTaggedPointerString

对于64位程序,为了节省内存和提高运行速度,苹果引入了Tagged Point技术,在运行时创建时对字符串的内容和长度作出判断,若字符串内容是由ASCII构成且长度较小(大概10个字符以内),这是创建的字符串就是NSTaggedPointerString类型,字符串直接存储在指针里,引用计数同样为-1,不适用对象的内存管理策略。

Tagged Pointer指针的值不再是地址,而是真正的值,所以它不再是一个对象,只是一个披着对象皮的普通变量而已。它的内存并不存储在堆中,OC对象的内存管理对其无效。

__NSCFConstantString

常量字符串,该类型的字符串是以字面量创建的,是在编译期创建的,保存在常量区

文字常量区存放常量字符串,程序结束后由系统释放,也就是说指向常量表的指针不受引用计数管理,OC的内存管理策略对其无效。

参考

  1. NSString 的内存问题