美文网首页iOS专攻
NSString的类型、存储位置

NSString的类型、存储位置

作者: han_zero | 来源:发表于2019-08-28 14:04 被阅读0次

    先来看一个例子:

    #if __has_feature(objc_arc)
    #define Obj_RetainCount(obj) CFGetRetainCount((__bridge CFTypeRef)(obj))
    #else
    #define Obj_RetainCount(obj) DebugLog(@"%lu",[obj retainCount]);
    #endif
    
    #define HFLog(_var) \
    NSLog(@"%@ : class = %@ p = %p retainCount = %ld",@#_var,NSStringFromClass([_var class]),_var,\
    (unsigned long)Obj_RetainCount(_var));
    
    
        NSString *a = @"str";
        NSString *b = [[NSString alloc] init];
        NSString *c = [[NSString alloc] initWithString:@"str"];
        
        NSString *d = [[NSString alloc] initWithFormat:@"<10"];
        NSString *e = [NSString stringWithFormat:@"<10"];
        NSString *f = [d copy];    
        NSString *g = [a copy];
        
        NSString *h = [[NSString alloc] initWithFormat:@"1234567890"];
        NSString *i = [NSString stringWithFormat:@"1234567890"];
    
        NSMutableString *mString1 = [NSMutableString stringWithString:@"<10"];
        NSMutableString *mString2 = [NSMutableString stringWithFormat:@"<10"];
        NSMutableString *mString3 = [[NSMutableString alloc] initWithFormat:@"1234567890"];
    
        HFLog(a);
        HFLog(b);
        HFLog(c);
        HFLog(d);
        HFLog(e);
        HFLog(f);
        HFLog(g);
        HFLog(h);
        HFLog(i)
        HFLog(mString1);
        HFLog(mString2);
        HFLog(mString3);
    

    输出结果为:
    <pre>
    a : class = __NSCFConstantString p = 0x107105b00 retainCount = 1152921504606846975
    b : class = __NSCFConstantString p = 0x107f62178 retainCount = 1152921504606846975
    c : class = __NSCFConstantString p = 0x107105b00 retainCount = 1152921504606846975
    d : class = NSTaggedPointerString p = 0xebeeae3f52cf0333 retainCount = 9223372036854775807
    e : class = NSTaggedPointerString p = 0xebeeae3f52cf0333 retainCount = 9223372036854775807
    f : class = NSTaggedPointerString p = 0xebeeae3f52cf0333 retainCount = 9223372036854775807
    g : class = NSTaggedPointerString p = 0xebeeae3f52cf0333 retainCount = 9223372036854775807
    h : class = __NSCFString p = 0x60000168f3c0 retainCount = 1
    i : class = __NSCFString p = 0x60000168f3e0 retainCount = 2
    mString1 : class = __NSCFString p = 0x60000310cb70 retainCount = 1
    mString2 : class = __NSCFString p = 0x60000310d260 retainCount = 2
    mString3 : class = __NSCFString p = 0x60000310d140 retainCount = 1
    </pre>

    可以看到,不同方式创建的字符串类型不同,引用计数也有所区别,并不是我们常规理解的对象初始化后引用计数为1。创建的字符串有3种类型

    • __NSCFConstantString
    • __NSCFString
    • __NSTaggedPointerString

    造成这种结果的原因是由于OC对字符串做的内存优化。

    __NSCFConstantString

    对变量类型名上就可以看出,这种类型的字符串是常量字符串。该类型的字符串以字面量的方式创建,保存在字符串常量区,是在编译时创建的。如上a,b,c,打印结果:

    <pre>
    class = __NSCFConstantString p = 0x107105b00 retainCount = 1152921504606846975
    </pre>

    对于 initWithString 实例方法以及 stringWithString 类方法,编译器会给出redundant警告,原因是该方法创建字符串等同于直接复制字符串字面量.
    当创建的字符串变量值在常量区已经存在时,会指向那个字符串,这是编译器做的优化。
    由于是常量,因此其内存管理并不同于对象的内存管理,引用计数用整形格式打出来始终为-1。(此处1152921504606846975打印为%ld,对象的引用计数是64位OS下无符号长整型的最大值,后面不做解释)。

    __NSCFString

    __NSCFString 表示对象类型的字符串,在运行时创建,保存在堆区,初始引用计数为1,其内存管理方式就是对象的内存管理方式。该种类型字符串通过format方式创建,并且字符串内容仅由数字、字母和常规ASCII字符构成,且其长度>=10,否则创建的是NSTaggedPointerString类型。

    如上h,i打印结果:
    <pre>
    h : class = __NSCFString p = 0x600003f33580 retainCount = 2
    i : class = __NSCFString p = 0x600003f32800 retainCount = 1
    </pre>
    可见当以format创建出来的字符串>9个时,会创建NSCFString类型,引用计数从1开始计算。
    此处

    个人的理解:format后面的字符串>9创建在堆上,引用计数初始为1,stringWith是对该字符串的引用,因此i的retainCount = 2,而h新获得的字符串是alloc init,重新开辟的内存,所以retainCount = 1。

    NSTaggedPointerString

    NSTaggedPointerString 类型的字符串是对__NSCFString类型的一种优化,在运行时创建字符串时,会对字符串内容及长度作判断,若内容由ASCII字符构成且长度<10,这时候创建的字符串类型就是 NSTaggedPointerString (标签指针字符串),字符串直接存储在指针的内容中。NSTaggedPointerString 类型的字符串引用计数同样为-1,不适用对象的内存管理策略。

    <pre>
    class = NSTaggedPointerString p = 0xebeeae3f52cf0333 retainCount = 9223372036854775807
    </pre>

    相关文章

      网友评论

        本文标题:NSString的类型、存储位置

        本文链接:https://www.haomeiwen.com/subject/baipectx.html