Xcode到底对NSString做了什么优化?

Xcode到底对NSString做了什么优化?

首先看个例子: 一般在OC中都是在堆中开辟一块内存存储对象, 但是NSString是有点区别的.

NSObject *obj1 = [[NSObject alloc]init];  //<NSObject: 0x100539310>
NSObject *obj2 = [[NSObject alloc]init];  //<NSObject: 0x100538a90>

结论:

  1. NSString对象如果通过字面量创建的话, 是存储在常量区的, 并且字面量相同的话, 是共占一份内存的
  2. NSString对象如果通过 stringWithString 或者 initWithString创建的, 值依然 是存储在常量区的, 并且值相同的话, 是共占一份内存的. 并且如果通过这两种方式创建字符串, 编译器会告诉你这是多余的 Using ‘stringWithString:’ with a literal is redundant 或者 Using ‘initWithString:’ with a literal is redundant, 建议你用字面量替换.
  3. NSString对象如果通过stringWithFormat 或者initWithFormat创建的, 对象是存储的堆区的, 如果字符串的值相同, 也是共占一份内存的.

为了探究Xcode到底对NSString做了什么优化, 分别使用字面量, 类方法, 对象方法创建3个字符串, 看看地址, 引用计数器,和值

// 1. 字面量
NSString *s1 = @"string1";
NSString *s1_1 = @"string1"; 

// 2. 类方法, 创建一个字符串的类方法有2种
NSString *s4 = [NSString stringWithString:@"string1"];
NSString *s5 = [NSString stringWithFormat:@"%@", @"string1"];

// 辅助证明
NSString *s6 = [NSString stringWithString:@"string1"];
NSString *s7 = [NSString stringWithFormat:@"%@", @"string1"];


// 3 对象方法 创建一个字符串的对象方法常用的也是2种
NSString *s10 = [[NSString alloc]initWithString:@"string1"];
NSString *s11 = [[NSString alloc]initWithFormat:@"string1"];

// 辅助证明
NSString *s12 = [[NSString alloc]initWithString:@"string1"];
NSString *s13 = [[NSString alloc]initWithFormat:@"string1"];

// 打印 地址, 引用计数器, 值
// 先打印部分对象
NSLog(@"s1: %p,  %ld,  %@", s1,(long)CFGetRetainCount(CFBridgingRetain(s1)),s1);
NSLog(@"s1_1: %p,  %ld,  %@", s1_1,(long)CFGetRetainCount(CFBridgingRetain(s1_1)),s1_1);
NSLog(@"s4: %p,  %ld,  %@", s4,(long)CFGetRetainCount(CFBridgingRetain(s4)),s4);
NSLog(@"s5: %p,  %ld,  %@", s5,(long)CFGetRetainCount(CFBridgingRetain(s5)),s5);
NSLog(@"s10: %p,  %ld,  %@", s10,(long)CFGetRetainCount(CFBridgingRetain(s10)),s10);
NSLog(@"s11 %p,  %ld,  %@", s11,(long)CFGetRetainCount(CFBridgingRetain(s11)),s11);

printf("\n------------------------分割线------------------------------\n");
// 打印辅助对象的地址, 计数器, 值
NSLog(@"s6: %p,  %ld,  %@", s6,(long)CFGetRetainCount(CFBridgingRetain(s6)),s6);
NSLog(@"s7: %p,  %ld,  %@", s7,(long)CFGetRetainCount(CFBridgingRetain(s7)),s7);
NSLog(@"s12: %p,  %ld,  %@", s12,(long)CFGetRetainCount(CFBridgingRetain(s12)),s12);
NSLog(@"s13: %p,  %ld,  %@", s13,(long)CFGetRetainCount(CFBridgingRetain(s13)),s13);



// 打印结果
2021-07-04 15:46:02.091105+0800 oc[13313:1719173] s1: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.091569+0800 oc[13313:1719173] s1_1: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.091655+0800 oc[13313:1719173] s4: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.091759+0800 oc[13313:1719173] s5: 0xe9c13f44bd0a3a69,  9223372036854775807,  string1
2021-07-04 15:46:02.091813+0800 oc[13313:1719173] s10: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.091873+0800 oc[13313:1719173] s11 0xe9c13f44bd0a3a69,  9223372036854775807,  string1

------------------------分割线------------------------------
2021-07-04 15:46:02.091935+0800 oc[13313:1719173] s6: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.091987+0800 oc[13313:1719173] s7: 0xe9c13f44bd0a3a69,  9223372036854775807,  string1
2021-07-04 15:46:02.092024+0800 oc[13313:1719173] s12: 0x100004018,  1152921504606846975,  string1
2021-07-04 15:46:02.092062+0800 oc[13313:1719173] s13: 0xe9c13f44bd0a3a69,  9223372036854775807,  string1
  1. 可以看到s1与s1_1 是用相同字面量创建的2个不同的对象, 但是他们的内存地址, 计数器, 值都是相同的, 可以证明结论1
  2. s4和s10是分别通过类方法和对象方法用一个字面量来创建的2个不同的对象, 可以看到他们的内存地址, 计数器, 值都是相同的, 并且与用字面量创建的s1的值是一样的, 可以证明结论2
  3. s5和s11是分别通过带format的类方法和带format的对象方法创建的2个对象, 他们的内存地址, 计数器, 值都是相同的, 但是与之前用字面量创建的字符串地址是不同的, 说明他们存在堆区, 并且他们两个共占一份内存, 证明结论3
  4. s6是通过stringWithString创建的新的对象, 它与字面量创建的对象完全一致, 进一步验证了结论
  5. s13是通过initWithFormat创建的一个新的对象, 它与s5完全一致, 进一步辅助验证了结论.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值