Copy & MutableCopy

引言:
深拷贝和浅拷贝已经是被别人说烂了的, 大家普遍的认知是:浅拷贝是只拷贝地址, 深拷贝不但拷贝地址也拷贝内容,当然也有人有不一样的认知,下面我们来看看具体的吧
我们先用NSString举例子(MRC)

创建NSString
NSString *str0 = @"0123456789";
NSString *str1 = [NSString stringWithString:@"0123456789"];
NSString *str2 = [NSString stringWithFormat:@"0123456789"];
NSString *str3 = [NSString stringWithFormat:@"abcd"];

第一种方式: 创建了存在常量区的字符串, retainCount = -1
第二种方式:和第一种方式一样, 但是已经被苹果抛弃掉了, 你写了应该回报警告的吧
第三种方式: 创建了存储在堆区的字符串, retainCount = 1
第四种方式:看着和第三种一样, 其实不一样, 为啥不一样我们往下看

2019-05-29 18:04:37.703233+0800 NSStringDemo[2322:134716] str0 : __NSCFConstantString -> 0x10abbb060 : 0123456789, -1
2019-05-29 18:04:37.703357+0800 NSStringDemo[2322:134716] str1 : __NSCFConstantString -> 0x10abbb060 : 0123456789, -1
2019-05-29 18:04:37.703448+0800 NSStringDemo[2322:134716] str2 : __NSCFString -> 0x60000075c7a0 : 0123456789, 1
2019-05-29 18:04:37.703555+0800 NSStringDemo[2322:134716] str3 : NSTaggedPointerString -> 0xe2f3673dfd6295f3 : abcd, -1

从打印的日志我们可以看出第四种方式创建出来的字符串确实和别人的不一样, 它是存储在栈区的字符串, retainCount = -1

对常量区的字符串来进行copy 、retain 、mutableCopy
- (void)test__NSCFConstantString {
    NSString *str = @"0123456789";
    TLog(str);
    
    NSString *str1 = [str retain];
    TLog(str1);
    
    NSString *str2 = [str copy];
    TLog(str2);
    
    NSString *str3 = [str mutableCopy];
    TLog(str3);
    
    NSString *str4 = [str3 copy];
    TLog(str4);
}

2019-05-29 18:12:47.426888+0800 NSStringDemo[2387:138593] str : __NSCFConstantString -> 0x100681060 : 0123456789, -1
2019-05-29 18:12:47.427000+0800 NSStringDemo[2387:138593] str1 : __NSCFConstantString -> 0x100681060 : 0123456789, -1
2019-05-29 18:12:47.427102+0800 NSStringDemo[2387:138593] str2 : __NSCFConstantString -> 0x100681060 : 0123456789, -1
2019-05-29 18:12:47.427240+0800 NSStringDemo[2387:138593] str3 : __NSCFString -> 0x6000019287b0 : 0123456789, 1
2019-05-29 18:12:47.427377+0800 NSStringDemo[2387:138593] str4 : __NSCFString -> 0x60000175c280 : 0123456789, 1

1、对一个__NSCFConstantString进行retain和copy操作都还是自己,没有任何变化
2、对其mutableCopy操作,就别变成了__NSCFString, 将其拷贝到堆上,retainCount为1.
3、对__NSCFString copy 在堆区拷贝一份, retainCount为1

堆区字符串
- (void)test__NSCFString {
    NSString *str0 = [NSString stringWithFormat:@"0123456789"];
    TLog(str0);
    
    NSString *str = [str0 mutableCopy];
    TLog(str);
    
    NSString *str1 = [str retain];
    TLog(str1);
    
    NSString *str2 = [str copy];
    TLog(str2);
    
    NSString *str3 = [str mutableCopy];
    TLog(str3);
    
    NSString *str4 = [str3 copy];
    TLog(str4);
}

2019-05-29 18:16:46.899326+0800 NSStringDemo[2437:141373] str0 : __NSCFString -> 0x600000595120 : 0123456789, 1
2019-05-29 18:16:46.899423+0800 NSStringDemo[2437:141373] str : __NSCFString -> 0x600000ba0de0 : 0123456789, 1
2019-05-29 18:16:46.899494+0800 NSStringDemo[2437:141373] str1 : __NSCFString -> 0x600000ba0de0 : 0123456789, 2
2019-05-29 18:16:46.899569+0800 NSStringDemo[2437:141373] str2 : __NSCFString -> 0x60000058bbe0 : 0123456789, 1
2019-05-29 18:16:46.899643+0800 NSStringDemo[2437:141373] str3 : __NSCFString -> 0x600000ba0fc0 : 0123456789, 1
2019-05-29 18:16:46.899709+0800 NSStringDemo[2437:141373] str4 : __NSCFString -> 0x60000058bd40 : 0123456789, 1

从结果可以看出:对堆区的字符串的操作符合我们一开始的理解

栈区字符串
- (void)testTaggedPointerString {
    NSString *shortStr = [NSString stringWithFormat:@"abcd"];
    TLog(shortStr);
    
    NSString *copyShortStr = [shortStr copy];
    TLog(copyShortStr);
    
    NSString *mutableCopyStr = [shortStr mutableCopy];
    TLog(mutableCopyStr);
    
    NSString *copyMutCopyStr = [mutableCopyStr copy];
    TLog(copyMutCopyStr);
}

2019-05-29 18:20:32.124531+0800 NSStringDemo[2474:143425] shortStr : NSTaggedPointerString -> 0xcb08639b235bbeeb : abcd, -1
2019-05-29 18:20:32.124665+0800 NSStringDemo[2474:143425] copyShortStr : NSTaggedPointerString -> 0xcb08639b235bbeeb : abcd, -1
2019-05-29 18:20:32.124814+0800 NSStringDemo[2474:143425] mutableCopyStr : __NSCFString -> 0x6000032a5530 : abcd, 1
2019-05-29 18:20:32.124951+0800 NSStringDemo[2474:143425] copyMutCopyStr : NSTaggedPointerString -> 0xcb08639b235bbeeb : abcd, -1

1、对栈区字符串copy, 也还是栈区字符串, retainCount是-1
2、对栈区字符串mutableCopy, 拷贝到了堆区, retainCount为1
3、对堆区的短的字符串进行copy, 又回到了栈区,变回了NSTaggedPointerString, retainCount为-1

你可能感兴趣的:(Copy & MutableCopy)