剖析【OC】中深复制与浅复制

在OC编程中,常常会用到对对象的复制,然后操作副本对象。然而对与应该选择何种对象复制的方式,复制后副本对象操作会不会影响原始对象等问题,我们往往没有过多考虑,而是凭借经验在编码。接下来就对OC中对象复制机制进行剖析,通过对复制机制的研究可以在编码中对对象的复制更加游刃有余。

首先,在OC中复制分为深复制与浅复制,一个比较认可的定义是:

深复制:复制对象引用与对象本身。
浅复制:只复制对象引用。


那么哪些操作才是浅复制,哪些操作是深复制?

所有的对象间赋值操作都是浅复制,仅仅复制了引用。如 CopyStr = Str1,这里CopyStr和Str1指向的同一内存地址,改变两者之间任何一个值,另一个都会随之改变。

试例代码:

void assignTest()
{
    printf("-----Assign Test-----\n\n");
    
    NSString *str1 = @"Hello";
    NSString *str2 = str1;
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [NSMutableString stringWithString:@"Hello"];
    NSMutableString *str4 = str3;
    [str3 appendString:@" World"];
    [str4 appendString:@"!"];
    printf("orignalStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str4 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str3);
    printf("copyStr value address: %p\n",str4);
    printf("orignalStr pointer address: %p\n",&str3);
    printf("copyStr pointer address: %p\n",&str4);
    printf("\n");
    
    NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:@"Hello", nil];
    NSMutableArray *arr2 = arr1;
    [arr1 addObject:@"World"];
    [arr2 addObject:@"!"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
}

输出结果:

-----Assign Test-----


orignalStr : Hello
copyStr : Hello
orignalStr value address: 0x100002060
copyStr value address: 0x100002060
orignalStr pointer address: 0x7fff5fbff7a8
copyStr pointer address: 0x7fff5fbff7a0


orignalStr : Hello World!
copyStr : Hello World!
orignalStr value address: 0x1002005c0
copyStr value address: 0x1002005c0
orignalStr pointer address: 0x7fff5fbff798
copyStr pointer address: 0x7fff5fbff790


2016-08-22 11:35:20.312 CopyDemo[2046:72936] orignalArray : (
** Hello,**
** World,**
** "!"**
)
2016-08-22 11:35:20.313 CopyDemo[2046:72936] copyArray : (
** Hello,**
** World,**
** "!"**
)
orignalArray value address: 0x100406910
copyArray value address: 0x100406910
orignalArray pointer address: 0x7fff5fbff788
copyArray pointer address: 0x7fff5fbff780


通过上面结果我们可以看到,value的地址都是一样的,而pointer的地址是不一样的,这就说明了赋值操作是浅复制,只是生成两份对象的引用,而对象本身还是同一份。原对象值和副本对象的值操作是相互影响的。


**那么OC中如何实现深复制呢? **

OC中深复制是通过copy与mutableCopy方法实现(但不是都能达到深复制的目的),通过copy复制后的副本都是不可变的,通过mutableCopy复制后的副本都是可变的。如初始对象为NSString与NSMutableString,通过copy后副本都是NSString,而通过mutableCopy后都是NSMutableString。
接下来分两种情况讨论copy与mutableCopy:

初始对象不可变(如NSString、NSArray等)

调用copy方法也是浅复制,等同于直接赋值,因为复制过后的副本和原来的对象都是不可变的,所以调用copy本质就是赋值操作,复制了引用,但是都指向同一内存地址。
调用mutableCopy是深复制,副本成为了可变对象,但是操作副本,对初始对象的值不会产生影响。

试例代码:

void constCopyTest()
{
    printf("-----ConstCopy Test-----\n\n");
    
    printf("-NSString Copy-\n");
    NSString *str1 = @"Hello";
    NSString *str2 = [str1 copy];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [str1 mutableCopy];
    [str3 appendString:@" World!"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str3);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str3);
    printf("\n");
    
    printf("-NSArray Copy-\n");
    NSArray *arr1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Hello"], nil];
    NSArray *arr2 = [arr1 copy];
    [[arr1 objectAtIndex:0] appendString:@" World!"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
    
    NSMutableArray *arr3 = [arr1 mutableCopy];
    [arr3 addObject:@"World"];
    [[arr1 objectAtIndex:0] appendString:@" + str1"];
    [[arr3 objectAtIndex:0] appendString:@" + str3"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr3);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr3);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr3);
    printf("\n");
}

输出结果:

-----ConstCopy Test-----


-NSString Copy-
orignalStr : Hello
copyStr : Hello
orignalStr value address: 0x100002060
copyStr value address: 0x100002060
orignalStr pointer address: 0x7fff5fbff7a8
copyStr pointer address: 0x7fff5fbff7a0


orignalStr : Hello
copyStr : Hello World!
orignalStr value address: 0x100002060
copyStr value address: 0x1004074d0
orignalStr pointer address: 0x7fff5fbff7a8
copyStr pointer address: 0x7fff5fbff798


-NSArray Copy-
2016-08-22 11:35:20.314 CopyDemo[2046:72936] orignalArray : (
** "Hello World!"**
)
2016-08-22 11:35:20.314 CopyDemo[2046:72936] copyArray : (
** "Hello World!"**
)
orignalArray value address: 0x1001016b0
copyArray value address: 0x1001016b0
orignalArray pointer address: 0x7fff5fbff790
copyArray pointer address: 0x7fff5fbff788


2016-08-22 11:35:20.314 CopyDemo[2046:72936] orignalArray : (
** "Hello World! + str1 + str3"**
)
2016-08-22 11:35:20.314 CopyDemo[2046:72936] copyArray : (
** "Hello World! + str1 + str3",**
** World**
)
orignalArray value address: 0x1001016b0
copyArray value address: 0x100300000
orignalArray pointer address: 0x7fff5fbff790
copyArray pointer address: 0x7fff5fbff780


输出结果可以看到,通过copy方法复制后的副本对象的value地址和原对象是一样的,所以针对不可变对象是用copy方法是浅复制。而mutableCopy方法复制后,副本对象的value和pointer地址都和原对象不一样了,说明mutableCopy方法是深复制。

初始对象可变(如NSMutableString、NSMutableArray等)

调用copy方法是深复制,因为这里副本是不可变的,所以只考虑初始对象改变。因为是深复制,初始对象无论怎么改变,副本的值都是不变的。
调用mutableCopy也是深复制,复制过后,副本与初始对象之间的改变都是独立不影响的,如初始对象str = “example”,str+” append1”,副本str+” append2”,最终输出结果会是初始对象为”example append1”,副本为”example append2”。

试例代码:

void mutableCopyTest()
{
    printf("-----MutableCopy Test-----\n\n");
    
    printf("-NSString Copy-\n");
    NSMutableString *str1 = [NSMutableString stringWithString:@"Hello"];
    NSString *str2 = [str1 copy];
    [str1 appendString:@" World"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [str1 mutableCopy];
    [str1 appendString:@" + str1"];
    [str3 appendString:@" + str3"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str3);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str3);
    printf("\n");
    
    printf("-NSArray Copy-\n");
    NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"Hello"], nil];
    NSArray *arr2 = [arr1 copy];
    [[arr1 objectAtIndex:0] appendString:@" World!"];
    [arr1 addObject:@"Word"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
    
    NSMutableArray *arr3 = [arr1 mutableCopy];
    [arr1 addObject:@"+arr1"];
    [arr3 addObject:@"+arr3"];
    [[arr1 objectAtIndex:0] appendString:@" + str1"];
    [[arr3 objectAtIndex:0] appendString:@" + str3"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr3);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr3);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr3);
    printf("\n");
}

输出结果:

-----MutableCopy Test-----


-NSString Copy-
orignalStr : Hello World
copyStr : Hello
orignalStr value address: 0x100300080
copyStr value address: 0x6f6c6c654855
orignalStr pointer address: 0x7fff5fbff7a8
copyStr pointer address: 0x7fff5fbff7a0


orignalStr : Hello World + str1
copyStr : Hello World + str3
orignalStr value address: 0x100300080
copyStr value address: 0x100300320
orignalStr pointer address: 0x7fff5fbff7a8
copyStr pointer address: 0x7fff5fbff798


-NSArray Copy-
2016-08-22 11:35:20.314 CopyDemo[2046:72936] orignalArray : (
** "Hello World!",**
** Word**
)
2016-08-22 11:35:20.314 CopyDemo[2046:72936] copyArray : (
** "Hello World!"**
)
orignalArray value address: 0x100300000
copyArray value address: 0x100300b00
orignalArray pointer address: 0x7fff5fbff790
copyArray pointer address: 0x7fff5fbff788


2016-08-22 11:35:20.314 CopyDemo[2046:72936] orignalArray : (
** "Hello World! + str1 + str3",**
** Word,**
** "+arr1"**
)
2016-08-22 11:35:20.314 CopyDemo[2046:72936] copyArray : (
** "Hello World! + str1 + str3",**
** Word,**
** "+arr3"**
)
orignalArray value address: 0x100300000
copyArray value address: 0x100300e40
orignalArray pointer address: 0x7fff5fbff790
copyArray pointer address: 0x7fff5fbff780


通过输出结果可以看到,对于可变对象,调用copy与mutableCopy方法都是深复制,因为副本的value和pointer地址都与原对象不同。

注:对于网上某些解释说NSArray/NSMutableArray NSDictionary/NSMutableDictionary只有浅复制,这里认为对于对象本身来说调用mutableCopy或对于可变对象调用copy都是深复制,只能说对于数组和字典这种复合结构深复制操作只是作用到外层对象,内部如果还有可变对象,仅仅就是引用的复制。(上面的例子中对于数组的第一个元素的操作可以很清楚的看出来。即使是对数组的深复制,然而改变第一个可变字符串,无论是副本数组还是原数组的第一个字符串都改变了。)

完整代码:

//
//  main.m
//  CopyDemo
//
//  Created by Jiao Liu on 6/23/16.
//  Copyright © 2016 ChangHong. All rights reserved.
//

#import <Foundation/Foundation.h>

void mutableCopyTest()
{
    printf("-----MutableCopy Test-----\n\n");
    
    printf("-NSString Copy-\n");
    NSMutableString *str1 = [NSMutableString stringWithString:@"Hello"];
    NSString *str2 = [str1 copy];
    [str1 appendString:@" World"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [str1 mutableCopy];
    [str1 appendString:@" + str1"];
    [str3 appendString:@" + str3"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str3);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str3);
    printf("\n");
    
    printf("-NSArray Copy-\n");
    NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"Hello"], nil];
    NSArray *arr2 = [arr1 copy];
    [[arr1 objectAtIndex:0] appendString:@" World!"];
    [arr1 addObject:@"Word"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
    
    NSMutableArray *arr3 = [arr1 mutableCopy];
    [arr1 addObject:@"+arr1"];
    [arr3 addObject:@"+arr3"];
    [[arr1 objectAtIndex:0] appendString:@" + str1"];
    [[arr3 objectAtIndex:0] appendString:@" + str3"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr3);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr3);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr3);
    printf("\n");
}

void constCopyTest()
{
    printf("-----ConstCopy Test-----\n\n");
    
    printf("-NSString Copy-\n");
    NSString *str1 = @"Hello";
    NSString *str2 = [str1 copy];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [str1 mutableCopy];
    [str3 appendString:@" World!"];
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str3);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str3);
    printf("\n");
    
    printf("-NSArray Copy-\n");
    NSArray *arr1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Hello"], nil];
    NSArray *arr2 = [arr1 copy];
    [[arr1 objectAtIndex:0] appendString:@" World!"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
    
    NSMutableArray *arr3 = [arr1 mutableCopy];
    [arr3 addObject:@"World"];
    [[arr1 objectAtIndex:0] appendString:@" + str1"];
    [[arr3 objectAtIndex:0] appendString:@" + str3"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr3);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr3);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr3);
    printf("\n");
}

void assignTest()
{
    printf("-----Assign Test-----\n\n");
    
    NSString *str1 = @"Hello";
    NSString *str2 = str1;
    printf("orignalStr : %s\n",[str1 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str2 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str1);
    printf("copyStr value address: %p\n",str2);
    printf("orignalStr pointer address: %p\n",&str1);
    printf("copyStr pointer address: %p\n",&str2);
    printf("\n");
    
    NSMutableString *str3 = [NSMutableString stringWithString:@"Hello"];
    NSMutableString *str4 = str3;
    [str3 appendString:@" World"];
    [str4 appendString:@"!"];
    printf("orignalStr : %s\n",[str3 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("copyStr : %s\n",[str4 cStringUsingEncoding:NSUTF8StringEncoding]);
    printf("orignalStr value address: %p\n",str3);
    printf("copyStr value address: %p\n",str4);
    printf("orignalStr pointer address: %p\n",&str3);
    printf("copyStr pointer address: %p\n",&str4);
    printf("\n");
    
    NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:@"Hello", nil];
    NSMutableArray *arr2 = arr1;
    [arr1 addObject:@"World"];
    [arr2 addObject:@"!"];
    NSLog(@"orignalArray : %@",arr1);
    NSLog(@"copyArray : %@",arr2);
    printf("orignalArray value address: %p\n",arr1);
    printf("copyArray value address: %p\n",arr2);
    printf("orignalArray pointer address: %p\n",&arr1);
    printf("copyArray pointer address: %p\n",&arr2);
    printf("\n");
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        assignTest();
        constCopyTest();
        mutableCopyTest();
    }
    return 0;
}

本文最早发布于长虹软服公众号,有兴趣的朋友可以去看一下:
剖析【OC】中深复制与浅复制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 1、对象拷贝有两种方式:浅复制和深复制。顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针;深复制是直接...
    滴答大阅读 770评论 0 2
  • 307、setValue:forKey和setObject:forKey的区别是什么? 答:1, setObjec...
    AlanGe阅读 1,546评论 0 1
  • iOS 集合的深复制与浅复制 概念 对象拷贝有两种方式:浅复制和深复制。顾名思义,浅复制,并不拷贝对象本身,仅仅是...
    难却却阅读 319评论 0 1
  • 1. 属性中copy与strong特性的区别 在开始学习浅复制(Shallow Copy)、深复制(Deep Co...
    pro648阅读 1,721评论 2 16