NSTaggedPointer

2020-07-19  本文已影响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啥都没做),
而且他的地址都是一样的,所以不会奔溃。
上一篇下一篇

猜你喜欢

热点阅读