美文网首页
NSTaggedPointer

NSTaggedPointer

作者: 三国韩信 | 来源:发表于2020-07-19 23:47 被阅读0次

    TaggedPointer是苹果引入的对内存管理进一步优化的一种策略。下面以NSString为例,说明它。showCode:

    一、用@"" 这种初始化的字符串
        NSString *string = @"123456";
        NSLog(@"%@,%p,%@",string,self.string,[string class]);
    
        打印结果:123456,  0x1076e9198,  __NSCFConstantString
    

    可以看出,这种情况下的string是一个__NSCFConstantString类型,看它的内存地址,比不是放在栈区,也不是堆区,是放在常量区的。可见__NSCFConstantString代表的是一个字符串常量。
    注: 这种写法也是一样的,[[NSString alloc] initWithString:@"222"];

    二、用stringWithFormat初始化的字符串
    NSString *  s1 = [NSString stringWithFormat:@"123456789"];
    NSLog(@"%@,%p,%@",s1,s1,[s1 class]);
    
    NSString *  s2 = [NSString stringWithFormat:@"1234567890"];
    NSLog(@"%@,%p,%@",s2,s2,[s2 class]);
    
    NSString *  s3 = [[NSString alloc] initWithFormat:@"123456789"];
    NSLog(@"%@,%p,%@",s3,s3,[s3 class]);
    
    NSString *  s4 = [[NSString alloc] initWithFormat:@"1234567890"];
    NSLog(@"%@,%p,%@",s4,s4,[s4 class]);
    
    打印结果:
    123456789,     0xdb939874c869cf6b,   NSTaggedPointerString
    1234567890,    0x600003bbb600,       __NSCFString
    123456789,     0xdb939874c869cf6b,   NSTaggedPointerString
    1234567890,    0x600003bd1000,       __NSCFString
    

    这里,就出现了NSTaggedPointerString。那么何为NSTaggedPointerString呢?
    是苹果对于一些小变量(小的数据,短的字符串)的一种表示的方式。(NSString、NSNumber)
    NSTaggedPointer类型的数据,它的表现形式为:地址+值。它的数据本身就存储在地址里,它不用另外的去开辟堆栈空间之类的,所以他也不适用于苹果对普通对象的那套retain/release模式。


    TaggedPointer

    那么多小的变量算是苹果所谓的小数据呢,网上传说的是字符串只要少于9个就是,所以上面的例子中分别用了9个和10个字符来实验。而且,多次初始化相同的NSTaggedPointerString,它的地址是不变的。

    正因为NSTaggedPointerString不存在retain和release的操作,所以面试中也经常被坑。如下题:

    - (void)taggedPointerDemo {
      
        self.queue = dispatch_queue_create("com.taggedPointer.cn", DISPATCH_QUEUE_CONCURRENT);
        
        for (int i = 0; i<10000; i++) {
            dispatch_async(self.queue, ^{
                self.nameStr = [NSString stringWithFormat:@"cooci"];
                 NSLog(@"%@",self.nameStr);
            });
        }
    }
    
    -(void)nomalStringDemo {
        self.queue = dispatch_queue_create("com.nomalString.cn", DISPATCH_QUEUE_CONCURRENT);
         NSLog(@"来了");
        for (int i = 0; i<10000; i++) {
            dispatch_async(self.queue, ^{
                self.nameStr = [NSString stringWithFormat:@"和谐学习,不急不躁,才能进步"];
                NSLog(@"%@",self.nameStr);
            });
        }
    }
    
    以上2个方法运行,哪个会奔溃?
    解析:上面都是多线程异步去调用的,nomalStringDemo这个方法会奔溃。原因是这个方法里多线程去对self.nameStr赋值,
    相当于调用了它的setter方法,它的setter方法里面有retain/release的操作,而这里又没有加锁,
    多线程去调用release的话,会出现对同一个对象多次release的情况,所以会奔溃。
    而第一方法不会奔溃,正是因为它的string是NSTaggedPointerString,它本身并不会去retain/release(或者说它的retain/release啥都没做),
    而且他的地址都是一样的,所以不会奔溃。
    

    相关文章

      网友评论

          本文标题:NSTaggedPointer

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