Objective-C中copy與mutableCopy問題

先說下概念,我們對變量的復(fù)制,其實(shí)就是在寫代碼的過程中,再定義多幾個(gè)不同名字的變量,讓他們都“等于”某一個(gè)變量,這個(gè)過程我認(rèn)為就是我們平常說的“復(fù)制”。

基本數(shù)據(jù)類型

對于基本數(shù)據(jù)類型,如int,double,BOOL這些,在賦值的過程中就是真正意義上的復(fù)制了,賦值時(shí)不僅把值傳遞到新的變量中,而且新的變量也 重新開辟了內(nèi)存 ,使得原來的變量和后來的變量所指的不是同一塊內(nèi)存,就如同現(xiàn)實(shí)中真的復(fù)制(克?。┝艘粋€(gè)新的一模一樣個(gè)體一樣。于是,我們把這種有 新開辟內(nèi)存 的復(fù)制,暫且先叫做 深復(fù)制(深復(fù)制也有分兩種,后面會說到)。

  • 實(shí)驗(yàn)代碼:
    int a = 0;
    int b = a;
    JMPLog(&a);
    JMPLog(&b);
  • 運(yùn)行結(jié)果:
0x7ffee662c1dc
0x7ffee662c1d8

結(jié)論1:所有基本數(shù)據(jù)類型的復(fù)制,都是深復(fù)制

非集合類型對象

所謂非集合類型對象,比較常用的就是NSString,下面就以NSString作為例子,說明copy和mutableCopy之間的區(qū)別,并與深復(fù)制淺復(fù)制進(jìn)行聯(lián)系。
首先展示一個(gè)錯(cuò)誤的示范,網(wǎng)上有很多關(guān)于copy和mutableCopy的文章,里面舉了這么一個(gè)例子:

    NSString *str1 = @"str1";
    NSString *str2 = [str1 copy];
    
    str1 = @"asdf";

    NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);

    /*輸出結(jié)果,修改str2 同理
       str1 = asdf str1P = 0x10776b1a0
       str2 = str1 str2P = 0x10776b180
     */

然后就說,因?yàn)閟tr2 = str1的時(shí)候,兩個(gè)字符串都是不可變的,指向的同一塊內(nèi)存空間中的 @"str1",是不可能變成@"abcd"的。所以這個(gè)時(shí)候,為了優(yōu)化性能,系統(tǒng)沒必要另外提供內(nèi)存,只生成另外一個(gè)指針,指向同一塊內(nèi)存空間就行。
但是當(dāng)你從新給 str1 或者str2賦值的時(shí)候,因?yàn)橹暗膬?nèi)容不可變,還有互不影響的原則下,這個(gè)時(shí)候,系統(tǒng)會從新開辟一塊內(nèi)存空間。

上面的解釋和代碼有個(gè)很嚴(yán)重的問題,當(dāng)執(zhí)行str1 = @"asdf";這行代碼的時(shí)候其實(shí)str1的指針已經(jīng)指向了新的字符串@“asdf”身上了,所以這并不能很好的說明深淺復(fù)制的問題。

言歸正傳,我們先討論對于不可變的非集合類型對象(這里用NSString作為例子),當(dāng)發(fā)送copy和mutableCopy消息后,新的對象的內(nèi)存情況。

  • 實(shí)驗(yàn)代碼:
    NSString *strA = @"strA";
    NSString *strB = [strA copy];
    NSString *strC = [strA mutableCopy];
    NSLog(@"Value -- strA: %@, strB: %@, strC: %@", strA, strB, strC);
    NSLog(@"Pointer -- strA: %p, strB: %p, strC: %p", &strA, &strB, &strC);
    NSLog(@"Pointer of value -- strA: %p, strB: %p, strC: %p", strA, strB, strC);
  • 運(yùn)行結(jié)果:
Value -- strA: strA, strB: strA, strC: strA
Pointer -- strA: 0x7ffee3adf1d8, strB: 0x7ffee3adf1d0, strC: 0x7ffee3adf1c8
Pointer of value -- strA: 0x10c124800, strB: 0x10c124800, strC: 0x6000009e0a80

結(jié)果分析:

  1. 可以看出,三個(gè)字符串的內(nèi)容都是一樣的,達(dá)到了我們對“復(fù)制”這個(gè)概念的目的。但是,字符串B和C是不是做到真正意義上的復(fù)制呢?我們要看B,C變量所指向的內(nèi)存地址(Pointer of value),結(jié)果顯示B的地址與A的地址一致(0x1039f0800),而C的地址則與A的不同(A: 0x1039f0800, C: 0x6000021f4450),所以只有C才是真正意義上的復(fù)制,也就是我們上面提到的 深復(fù)制 ,而像字符串B這種 只是把指針指向同一塊內(nèi)存地址,而實(shí)現(xiàn)對應(yīng)內(nèi)容“復(fù)制” 的做法,我們稱之為 淺復(fù)制。
  2. 觀察三個(gè)字符串變量本身的地址(注意不是字符串所指向的地址),發(fā)現(xiàn)三個(gè)是不同的,也就是說上述行為是新建了三個(gè)指針(指針本身也占有內(nèi)存),然后A,B指向的是同一塊地址,C則指向另一塊新的地址,這些內(nèi)存地址的內(nèi)容都是@“strA”。
    就目前來看,我們暫時(shí)可以得出的結(jié)論是,copy的作用僅僅是把指針指向同一塊內(nèi)存地址,是淺復(fù)制,那么如果有其他手段能夠改變該段內(nèi)存的內(nèi)容,那么用copy消息返回的對象的值(所指內(nèi)存的內(nèi)容)也會跟著原本被“復(fù)制”的對象而改變。而mutableCopy的作用則會新開辟一段內(nèi)存,讓對象指向該段內(nèi)存,從而實(shí)現(xiàn)復(fù)制,如果被復(fù)制的對象內(nèi)容改變,新對象的內(nèi)容并不會跟著改變(由于指向的不是同一段內(nèi)存)。

接下來再討論可變非集合類型的對象(這里用NSMutableString作為例子),先上代碼

  • 實(shí)驗(yàn)代碼:
    NSMutableString *strA = [NSMutableString stringWithFormat:@"strA"];
    NSString *copyStr = [strA copy];
    NSString *copyStr2 = [strA copy];
    NSMutableString *copyMStr = [strA copy];
    NSMutableString *copyMStr2 = [strA copy];
    NSString *mutableCopyStr = [strA mutableCopy];
    NSString *mutableCopyStr2 = [strA mutableCopy];
    NSMutableString *mutableCopyMStr = [strA mutableCopy];
    NSMutableString *mutableCopyMStr2 = [strA mutableCopy];
    
    NSLog(@"strA -- %p &strA -- %p", strA, &strA);
    NSLog(@"copyStr -- %p &copyStr -- %p", copyStr, &copyStr);
    NSLog(@"copyStr2 -- %p &copyStr2 -- %p", copyStr2, &copyStr2);
    NSLog(@"copyMStr -- %p &copyMStr -- %p", copyMStr, &copyMStr);
    NSLog(@"copyMStr2 -- %p &copyMStr2 -- %p", copyMStr2, &copyMStr2);
    NSLog(@"mutableCopyStr -- %p &mutableCopyStr -- %p", mutableCopyStr, &mutableCopyStr);
    NSLog(@"mutableCopyStr2 -- %p &mutableCopyStr2 -- %p", mutableCopyStr2, &mutableCopyStr2);
    NSLog(@"mutableCopyMStr -- %p &mutableCopyMStr -- %p", mutableCopyMStr, &mutableCopyMStr);
    NSLog(@"mutableCopyMStr2 -- %p &mutableCopyMStr2 -- %p", mutableCopyMStr2, &mutableCopyMStr2);
  • 運(yùn)行結(jié)果:
strA -- 0x600001c093e0 &strA -- 0x7ffeebd531d8
copyStr -- 0xd4d03e2a99e5492a &copyStr -- 0x7ffeebd531d0
copyStr2 -- 0xd4d03e2a99e5492a &copyStr2 -- 0x7ffeebd531c8
copyMStr -- 0xd4d03e2a99e5492a &copyMStr -- 0x7ffeebd531c0
copyMStr2 -- 0xd4d03e2a99e5492a &copyMStr2 -- 0x7ffeebd531b8
mutableCopyStr -- 0x600001c08930 &mutableCopyStr -- 0x7ffeebd531b0
mutableCopyStr2 -- 0x600001c08a50 &mutableCopyStr2 -- 0x7ffeebd531a8
mutableCopyMStr -- 0x600001c08f30 &mutableCopyMStr -- 0x7ffeebd531a0
mutableCopyMStr2 -- 0x600001c09290 &mutableCopyMStr2 -- 0x7ffeebd53198

結(jié)果分析:

  • 同樣,觀察每個(gè)指針自身的地址各不相同,說明也是生成了各個(gè)不同的指針,符合邏輯。觀察使用copy消息的4個(gè)變量,發(fā)現(xiàn)無論是NSString還是NSMutableString,只要是copy消息返回的都是與原字符串A不同指向的地址。但是返回的這些指針,都是指向同一塊新的內(nèi)存地址(0xd4d03e2a99e5492a)。當(dāng)字符串A是可變字符串,copy消息返回了新的對象,開辟了新的內(nèi)存,這些對象都會指向新開辟的這一段內(nèi)存。根據(jù)前面描述的,這種復(fù)制應(yīng)該是深復(fù)制,這與上一個(gè)例子的非可變類型有所區(qū)別。
  • 對于mutableCopy,與copy的情況有類似的地方,都是返回的是與原字符串A不同指向的地址。不同的是,這些指針指向的卻是不是同一塊內(nèi)存地址,無論我們定義的是NSString或者是NSMutableString,每個(gè)新的對象都是指向一塊全新的地址。不過我們目前只考慮是否開辟了新的內(nèi)存,所以這種情況也是認(rèn)為是深復(fù)制。

結(jié)論2:

- 非可變非集合類型 可變非集合類型
copy 淺復(fù)制 深復(fù)制
mutableCopy 深復(fù)制 深復(fù)制

集合類型對象

集合類型對象應(yīng)該是我們開發(fā)過程中最常用到的結(jié)構(gòu)之一,比如NSArray,NSDictionary等。那么對于集合類型的對象,我們向他們發(fā)送copy和mutableCopy消息時(shí),又會產(chǎn)生何種效果?
首先還是討論不可變的情況,這里以NSDictionary作為例子(選擇字典作為例子是想更全面的研究字典中的Key和Value出現(xiàn)的情況是否相同,數(shù)組則體現(xiàn)不出這個(gè)效果)。

  • 實(shí)驗(yàn)代碼:
    NSDictionary *aDic = @{@"aaa": @"111"};
    
    NSDictionary *copyDic = [aDic copy];
    NSDictionary *copyDic2 = [aDic copy];
    NSMutableDictionary *copyMDic = [aDic copy];
    NSMutableDictionary *copyMDic2 = [aDic copy];
    
    NSDictionary *mutableCopyDic = [aDic mutableCopy];
    NSDictionary *mutableCopyDic2 = [aDic mutableCopy];
    NSMutableDictionary *mutableCopyMDic = [aDic mutableCopy];
    NSMutableDictionary *mutableCopyMDic2 = [aDic mutableCopy];

    NSLog(@"aDic -- %p aDic[@\"aaa\"] -- %p key aaa -- %p", aDic, aDic[@"aaa"], [[aDic allKeys] firstObject]);
    
    NSLog(@"copyDic -- %p copyDic[@\"aaa\"] -- %p key aaa -- %p", copyDic, copyDic[@"aaa"], [[copyDic allKeys] firstObject]);
    NSLog(@"copyDic2 -- %p copyDic2[@\"aaa\"] -- %p key aaa -- %p", copyDic2, copyDic2[@"aaa"], [[copyDic2 allKeys] firstObject]);
    NSLog(@"copyMDic -- %p copyMDic[@\"aaa\"] -- %p key aaa -- %p", copyMDic, copyMDic[@"aaa"], [[copyMDic allKeys] firstObject]);
    NSLog(@"copyMDic2 -- %p copyMDic2[@\"aaa\"] -- %p key aaa -- %p", copyMDic2, copyMDic2[@"aaa"], [[copyMDic2 allKeys] firstObject]);
    
    NSLog(@"mutableCopyDic -- %p mutableCopyDic[@\"aaa\"] -- %p key aaa -- %p", mutableCopyDic, mutableCopyDic[@"aaa"], [[mutableCopyDic allKeys] firstObject]);
    NSLog(@"mutableCopyDic2 -- %p mutableCopyDic2[@\"aaa\"] -- %p key aaa -- %p", mutableCopyDic2, mutableCopyDic2[@"aaa"], [[mutableCopyDic2 allKeys] firstObject]);
    NSLog(@"mutableCopyMDic -- %p mutableCopyMDic[@\"aaa\"] -- %p key aaa -- %p", mutableCopyMDic, mutableCopyMDic[@"aaa"], [[mutableCopyMDic allKeys] firstObject]);
    NSLog(@"mutableCopyMDic2 -- %p mutableCopyMDic2[@\"aaa\"] -- %p key aaa -- %p", mutableCopyMDic2, mutableCopyMDic2[@"aaa"], [[mutableCopyMDic2 allKeys] firstObject]);
  • 運(yùn)行結(jié)果:
aDic -- 0x6000027a1e00 aDic[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
copyDic -- 0x6000027a1e00 copyDic[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
copyDic2 -- 0x6000027a1e00 copyDic2[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
copyMDic -- 0x6000027a1e00 copyMDic[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
copyMDic2 -- 0x6000027a1e00 copyMDic2[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
mutableCopyDic -- 0x6000027a16e0 mutableCopyDic[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
mutableCopyDic2 -- 0x6000027a1d40 mutableCopyDic2[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
mutableCopyMDic -- 0x6000027a1920 mutableCopyMDic[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800
mutableCopyMDic2 -- 0x6000027a0ee0 mutableCopyMDic2[@"aaa"] -- 0x1042da820 key aaa -- 0x1042da800

結(jié)果分析:

  • 情況和非集合類型相似,對于被復(fù)制的對象是不可變集合類型,當(dāng)向?qū)ο蟀l(fā)送copy消息時(shí),無論新定義的對象是可變還是不可變的,返回的總是和原對象所指向的地址一樣的地址,同時(shí),字典里無論是key還是value都是和原對象是一致的。這還是比較符合認(rèn)知,既然所有的指針都指向同一個(gè)地址,證明這里copy消息只是做了一個(gè)淺復(fù)制,既然是淺復(fù)制,本質(zhì)上并沒有真正“復(fù)制”一個(gè)新的對象出來(沒有開辟新的內(nèi)存地址),而是只是簡單地把新的對象指向了原來對象的地址,所以沒有新的字典和內(nèi)容生成,故所有地址都是一致的。
  • 當(dāng)向?qū)ο蟀l(fā)送mutableCopy消息時(shí),無論新定義的對象是可變還是不可變的,返回的總是一段全新的內(nèi)存,指向全新的地址,不過有趣的是,字典里的key和value也是像前面copy的情況一樣,都是和原對象是一致。這就有點(diǎn)奇妙了,討論到現(xiàn)在,對于復(fù)制我們討論到的就兩種復(fù)制,淺復(fù)制和深復(fù)制,區(qū)分它們的方法就是看是否有開辟新的內(nèi)存,但現(xiàn)在的情況是,mutableCopy確實(shí)是返回了新開辟內(nèi)存的新的字典對象,但字典里面的內(nèi)容卻和原對象的是指向同一塊地址,也就是說如果通過某些手段改變了這些地址的值,所有這些新的字典對象的key和value也會隨之改變。這還是跟我們理解中的復(fù)制有點(diǎn)區(qū)別。所以這里回應(yīng)到一開始提到的深復(fù)制也有兩種情況,一種是單單給對象開辟新的內(nèi)存,另一種是 不僅給新的對象開辟內(nèi)存,而且會對其里面包含的內(nèi)容開辟新的地址,徹底復(fù)制一份全新的獨(dú)立的拷貝 ,我們把后者這種深復(fù)制叫做 兩層深復(fù)制 (two-layer-copy),同時(shí)為了區(qū)分,現(xiàn)在我們把第一種的深復(fù)制叫做 單層深復(fù)制。

接下來把可變集合類型也測試一下。

  • 實(shí)驗(yàn)代碼
    NSMutableDictionary *aDic = [NSMutableDictionary dictionaryWithCapacity:10];
    [aDic setObject:@"111" forKey:@"aaa"];
    
    NSDictionary *copyDic = [aDic copy];
    NSDictionary *copyDic2 = [aDic copy];
    NSMutableDictionary *copyMDic = [aDic copy];
    NSMutableDictionary *copyMDic2 = [aDic copy];
    
    NSDictionary *mutableCopyDic = [aDic mutableCopy];
    NSDictionary *mutableCopyDic2 = [aDic mutableCopy];
    NSMutableDictionary *mutableCopyMDic = [aDic mutableCopy];
    NSMutableDictionary *mutableCopyMDic2 = [aDic mutableCopy];
    
    NSLog(@"aDic -- %p aDic[@\"aaa\"] -- %p key aaa -- %p", aDic, aDic[@"aaa"], [[aDic allKeys] firstObject]);
    
    NSLog(@"copyDic -- %p copyDic[@\"aaa\"] -- %p key aaa -- %p", copyDic, copyDic[@"aaa"], [[copyDic allKeys] firstObject]);
    NSLog(@"copyDic2 -- %p copyDic2[@\"aaa\"] -- %p key aaa -- %p", copyDic2, copyDic2[@"aaa"], [[copyDic2 allKeys] firstObject]);
    NSLog(@"copyMDic -- %p copyMDic[@\"aaa\"] -- %p key aaa -- %p", copyMDic, copyMDic[@"aaa"], [[copyMDic allKeys] firstObject]);
    NSLog(@"copyMDic2 -- %p copyMDic2[@\"aaa\"] -- %p key aaa -- %p", copyMDic2, copyMDic2[@"aaa"], [[copyMDic2 allKeys] firstObject]);
    
    NSLog(@"mutableCopyDic -- %p mutableCopyDic[@\"aaa\"] -- %p key aaa -- %p", mutableCopyDic, mutableCopyDic[@"aaa"], [[mutableCopyDic allKeys] firstObject]);
    NSLog(@"mutableCopyDic2 -- %p mutableCopyDic2[@\"aaa\"] -- %p key aaa -- %p", mutableCopyDic2, mutableCopyDic2[@"aaa"], [[mutableCopyDic2 allKeys] firstObject]);
    NSLog(@"mutableCopyMDic -- %p mutableCopyMDic[@\"aaa\"] -- %p key aaa -- %p", mutableCopyMDic, mutableCopyMDic[@"aaa"], [[mutableCopyMDic allKeys] firstObject]);
    NSLog(@"mutableCopyMDic2 -- %p mutableCopyMDic2[@\"aaa\"] -- %p key aaa -- %p", mutableCopyMDic2, mutableCopyMDic2[@"aaa"], [[mutableCopyMDic2 allKeys] firstObject]);
  • 運(yùn)行結(jié)果:
aDic -- 0x600002f53240 aDic[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
copyDic -- 0x600002f53220 copyDic[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
copyDic2 -- 0x600002f531a0 copyDic2[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
copyMDic -- 0x600002f52d20 copyMDic[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
copyMDic2 -- 0x600002f52f00 copyMDic2[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
mutableCopyDic -- 0x600002f52de0 mutableCopyDic[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
mutableCopyDic2 -- 0x600002f52d60 mutableCopyDic2[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
mutableCopyMDic -- 0x600002f52e00 mutableCopyMDic[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820
mutableCopyMDic2 -- 0x600002f52e60 mutableCopyMDic2[@"aaa"] -- 0x10709f800 key aaa -- 0x10709f820

結(jié)果分析:

  • 情況有點(diǎn)出乎我預(yù)料,本來以為是跟非集合類型(NSString)類似,用copy消息返回的是一段新開辟的內(nèi)存(深復(fù)制),所有4個(gè)指針都是指向那段新開的內(nèi)存。但現(xiàn)實(shí)的情況確實(shí)每個(gè)對象各自指向了不同的新的內(nèi)存,盡管都是深復(fù)制。而且這里提到的深復(fù)制,是我們上述的單層深復(fù)制,因?yàn)榭梢钥闯鲎值涞腒ey和value都是跟原來的字典一樣的。
  • 同時(shí),mutableCopy就和之前的完全一致了,每個(gè)對象都各自開辟了新的互不相同的內(nèi)存,然而字典內(nèi)容也還是和原字典的一致,同樣也是單程深復(fù)制。

結(jié)論3:

- 不可變集合類型 可變集合類型
copy 淺復(fù)制 單層深復(fù)制
mutableCopy 單層深復(fù)制 單層深復(fù)制

彩蛋:在一開始的時(shí)候,我是把key和value都設(shè)置成@“aaa”,運(yùn)行后發(fā)現(xiàn)key和value的地址都是一樣的,這不就是淺復(fù)制嗎?猜測系統(tǒng)這樣的做法是為了節(jié)省內(nèi)存吧?

最終結(jié)論

所以,我們可以得出:
對于不可變的非集合類對象進(jìn)行 copy 操作,其內(nèi)存地址并沒有發(fā)生變化,屬于淺復(fù)制;進(jìn)行 mutableCopy 操作,內(nèi)存地址發(fā)生了變化,深復(fù)制。

對于不可變的集合類對象進(jìn)行 copy 操作,其內(nèi)存地址并沒有發(fā)生變化,屬于淺復(fù)制;進(jìn)行 mutableCopy 操作,內(nèi)存地址發(fā)生了變化,但是其中的內(nèi)容的內(nèi)存地址并沒有發(fā)生變化,屬于單層深復(fù)制。

對于可變集合類對象,不管是進(jìn)行 copy 操作還是 mutableCopy 操作,其內(nèi)存地址都發(fā)生了變化,但是其中的元素內(nèi)存地址都沒有發(fā)生變化,屬于單層深復(fù)制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,656評論 1 32
  • 前言 不敢說覆蓋OC中所有copy的知識點(diǎn),但最起碼是目前最全的最新的一篇關(guān)于 copy的技術(shù)文檔了。后續(xù)發(fā)現(xiàn)有新...
    zyydeveloper閱讀 3,715評論 4 35
  • 1.設(shè)計(jì)模式是什么? 你知道哪些設(shè)計(jì)模式,并簡要敘述?設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,302評論 0 12
  • 導(dǎo)讀 最近經(jīng)常在關(guān)注的公眾號或者技術(shù)網(wǎng)站看到關(guān)于 iOS 深拷貝與淺拷貝的話題??吹揭黄夹g(shù)文章,點(diǎn)擊收藏或者只是...
    獨(dú)木舟的木閱讀 733評論 0 8
  • 1.淺拷貝 所謂的淺拷貝,就是指只是將對象內(nèi)存地址多了一個(gè)引用,也就是說,拷貝結(jié)束之后,兩個(gè)對象的值不僅相同,而且...
    小瓶子Zgp閱讀 1,897評論 1 2

友情鏈接更多精彩內(nèi)容