關(guān)于深拷貝、淺拷貝和可變拷貝

經(jīng)常在論壇和群里看到有人問拷貝相關(guān)的問題,回答的總是五花八門、千奇百怪。如果你對幾種拷貝的概念還不是很清晰,這篇文章會有幫助。

什么是淺拷貝

在談?wù)撋羁截?、淺拷貝等概念之前,先要清楚什么叫拷貝??截悾╟opy)就是復(fù)制。當(dāng)我們已經(jīng)有一個對象例如:

NSString *str = @"abc";

那么我想有一個str2和str的值一樣該怎么做呢?最簡單的辦法就是這樣:

NSString *str2 = str;

實際上,這就是淺拷貝,str和str2的內(nèi)存地址是一樣的。也就是說兩個指針指向了同一塊內(nèi)存,因此實際上并沒有東西被復(fù)制出來,就好比文件的快捷方式,無論一個文件有多少快捷方式,這個文件始終只有一個。那么如果我不想要快捷方式,就想要兩個文件呢?

NSString *str3 = [str copy];

理論上來說,這樣會劃分新的內(nèi)存地址,生成新的對象,但是實際打印會發(fā)現(xiàn)str和str3的地址是一樣的。這是因為OC對NSString做了內(nèi)存管理的優(yōu)化,這種值相同的string會直接淺拷貝。這也說明,正常情況下NSString是不需要深拷貝的。

什么是深拷貝

那么什么時候需要深拷貝呢?其實深拷貝在開發(fā)中經(jīng)常用到:

@property (nonatomic, copy) NSString *name;

類似這樣的屬性項目中肯定多的數(shù)不清(當(dāng)然如果你寫成@property (nonatomic, strong) NSString *name;是不對的,你的項目會有可能出現(xiàn)莫名其妙的bug)。見名知意,聲明為copy的屬性在被賦值的時候?qū)嶋H上是會執(zhí)行copy方法的,就像這樣:

- (void)setName:(NSString *)name{
    _name = [name copy];
}

為什么要這么做呢?假如我們就將name聲明為strong。NSString有個子類NSMutableString,我們是可以將NSMutableString對象賦值給NSString的,像這樣:

NSMutableString *mutableName = [NSMutableString stringWithString:@"Mike"];
self.name = mutableName;

然而如果我們在后面的代碼中修改了mutableName的值,name的值也會隨之改變。這當(dāng)然是不合理的,NSString的值應(yīng)該是不變的。而copy的作用就是這個。通過copy方法,創(chuàng)建了一個新的值和mutableName相同的對象,所以mutableName的值改變并不會影響到name。

什么是可變拷貝mutableCopy

同樣見名知意,就是拷貝出一個可變的對象出來。例如:

NSMutableString *mutableStr = [@"abc" mutableCopy];

通過對NSString進(jìn)行mutableCopy而產(chǎn)生了一個NSMutableString。我見過一些人創(chuàng)建mutableString就是這樣寫的,但是從代碼規(guī)范和效率的角度講,這樣做是不推薦的。

copy的妙用

copy方法除了可以對對象進(jìn)行深拷貝以外還有個優(yōu)點就是,相比于重新創(chuàng)建一個對象,copy的效率更高。例如要創(chuàng)建一百個MyClass對象,實例化一個對象然后使用copy方法的效率要比實例化一百次高得多。

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

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

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