NSString、NSMutableString的内存地址类型

    NSString *a1 = [[NSString alloc] initWithFormat:@"stringTestTwo"];
    __weak NSString *a2 = a1;
    NSLog(@"a1:%@", a1);
    NSLog(@"a2:%@", a2);
    a1 = nil;
    NSLog(@"a1:%@", a1);

    NSLog(@"a2:%@", a2);

结果如下:

NSString、NSMutableString的内存地址类型

    NSString *string = @"string";

    NSString *string2 = @"stringTestTwo";
    NSString *string3 = [[NSString alloc] initWithFormat:@"string"];
    NSString *string4 = [[NSString alloc] initWithFormat:@"stringTestTwo"];

    NSLog(@"%@,%@,%@,%@",string,string2,string3,string4);

内存地址如下图:

NSString、NSMutableString的内存地址类型

string、string2被分配在常量区,string3也类似,就算使用assign、weak,a1被置空后,也不用担心a2被释放掉。

其中string、string2这种直接引用字面量,使用__NSCFConstantString类进行存储。

string3因为太短了,编译器做了优化,对短的不可变字符串,就使用了NSTaggedPointerString类进行存储。NSTaggedPointerString这个类型是标签指针字符串,这是苹果在64位环境下对 NSString,NSNumber 等对象做的一些优化。简单来讲可以理解为把指针指向的内容直接放在了指针变量的内存地址中,因为在64位环境下指针变量的大小达到了8位足以容纳一些长度较小的内容。于是使用了标签指针这种方式来优化数据的存储方式。

而string4就长些,使用__NSCFString类进行存储,它被分配在堆里面,使用assign、weak的话,a1被置空后,a2就会被释放掉。

string5、string6虽然存的可变字符串,但和string4一样,使用__NSCFString类进行存储。但不要不要以为string4也可以调用可变字符串的任意方法,第77行代码就会崩溃的。string5和string3的长度一样,但存储使用的类不一样。

由上可知:__NSCFConstantString继承于__NSCFString,__NSCFString继承于NSMutableString;NSTaggedPointerString继承于NSString,isa显示是空的。