NSTaggedPointerString,__NSCFConstantString,__NSCFString和NSString的关系?NSString为什么用copy?

​​​​问题引入:
NSString都存储在堆区吗?会不会存在栈区,或者数据区呢?

NSString用copy修饰还是strong修饰?NSString调用copy和mutableCopy会创建一个新的内存空间吗?NSMutableString用copy修饰会导致什么样的后果?

一.各类型字符串的关系和存储方式
NSString和NSMutableString相信我们平时都用过n遍了,但NSString真的都是一个存储在堆区的对象吗?如果在不同区,对它们进行copy操作,内存地址又会是什么样呢?

几个需要注意的点:

内存地址由低到高分别为:程序区-->数据区-->堆区-->栈区

                                            其中堆区分配内存从低往高分配,栈区分配内存从高往低分配

1.继承关系:

NSTaggedPointerString(栈区)      ---> NSString

__NSCFConstantString(数据常量区)  ---> __NSCFString (堆区) --->NSMutableString --->NSString

 

2.对于NSStringFromClass()方法,字符串较短的class,系统会对其进行比较特殊的内存管理,NSObject字符串比较短,直接存储在栈区,类型为NSTaggedPointerString,不论你NSStringFromClass多少次,得到的都是同一个内存地址的string;但对于较长的class,则为__NSCFString类型,而NSCFString存储在堆区,每次NSStringFromClass都会得到不同内存地址的string

3.__NSCFConstantString类型的字符串,存储在数据区,即使当前控制器被dealloc释放了,存在于这个控制器的该字符串所在内存仍然不会被销毁.通过快捷方式创建的字符串,无论字符串多长或多短,都是__NSCFConstantString类型,存储在数据区.

下面是实际代码测试的结果,对象内存地址和指针内存地址都作了相应注释:
 

    NSString *str1 = @"abcdeefghijk";//该种方式无论字符串多长,都是__NSCFConstantString类型,存储在数据区,0x0000000104b2c400
    NSString *strDigital = @"999";//即使很短,也是(__NSCFConstantString *)类型, 0x00000001092b1420,存储在数据区
 
    
    NSString *str1Copy = [str1 copy];//__NSCFConstantString,NSString类型的str1进行copy是浅拷贝,并不会拷贝一份新的内存地址,0x0000000104b2c400,内存地址和str1相同
    NSMutableString *str1MutableCopy = [str1 mutableCopy];//__NSCFString,NSString类型str1进行mutableCopy后是深拷贝,0x0000600000d7d590
    
    
    NSMutableString *str1MutaCopyCopy = [str1MutableCopy copy];//__NSCFString,mutableString类型的str1MutableCopy进行mutableCopy后是深拷贝,0x0000600000373980
    [str1MutableCopy appendString:@"12"];
   [str1MutaCopyCopy appendString:@"34"];//本行代码崩溃,原因是mutableString进行copy虽然是深拷贝,但返回的是不可变类型,只有NSMutableString才有appendString方法,__NSCFString没有appendString方法;虽然用NSMutableString接收,但str1MutaCopyCopy的类型还是由实际运行过程决定
    
    
    NSString * cfStringLongClass = NSStringFromClass([ViewController class]);//较长类情况下,该方法获得的字符串是类型__NSCFString存储在堆区,0x00006000003739a0
    NSString *taggedStrShortClass = NSStringFromClass([NSObject class]);//较短类情况下,该方法获得的字符串是NSTaggedPointerString类型,存储在栈区,0x86b1d57ef6188519
    
    NSString *taggedStrShortClassCopy = [taggedStrShortClass copy];//(NSTaggedPointerString *) $0 = 0xac71e37414f16209 @"NSObject" 内存地址不会变,浅拷贝,值也相同
    
    NSString *taggedStrShortClassMutaCopy = [taggedStrShortClass mutableCopy];//(__NSCFString *) $2 = 0x00006000036f4030 @"NSObject",内存地址变化,深拷贝一份至堆区,值相同,
 
    NSObject *obj = [[NSObject alloc]init];//对象存储在堆区,0x0000600000c61160
    
    
 
    
    //总结:stringWithFormat方式,最终字符串的类型由字符串长度决定,少于10个字符类型为NSTaggedPointerString,否则为__NS
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值