iOS中的深拷貝和淺拷貝以及copy關鍵字總結

參考文獻《招聘一個靠譜的iOS》


深拷貝和淺拷貝

由上面的圖我們可以明確地看出,

淺拷貝(Shallow copy)可以說是指針復制,它們指向共同的內存地址,沒有產生新的對象,源對象和副本對象是同一對象,相當于做一次retain操作,引用計數加1

深拷貝(Deep copy)是指內容拷貝,分別指向了不同的內存地址,它產生的新的對象,源對象的引用計數不變,副本對象的引用計數為1.


什么集合類對象和非集合類對象

非集合類對象(NSString,NSMutableString,NSData,NSNumber)

集合類對象(NSArray,NSMutableArray,NSDictionary,NSSet...)


系統對象的copy與mutableCopy方法

- (id)copy;

- (id)mutableCopy;

不管是集合類對象,還是非集合類對象,接收到copy和mutableCopy消息時,都遵循以下準則:

1.copy返回imutable對象;所以,如果對copy返回值使用mutable對象接口就會crash

2.mutableCopy返回mutable對象;

那什么是imutable對象和mutable對象?

imutable對象就是不可變的對象。像NSString不可以拼接字符串、NSArray也不可添加元素...這種就是不可變對象。

mutable對象就是可變的對象。像NSMutableArray可以動態添加元素,NSMutableString可以拼接字符串...這種就是可變的對象。

舉個例子:

NSMutableString 通過 copy 返回的是 NSString 對象,但是因為返回值是id類型,所以我們可以使用NSMutableString來接收,但是,當你使用NSMutableString獨有的對象接口的時候,就會crash,提示找不到對應的API.

NSString 通過 mutableCopy 返回的是 NSMutableString對象


例子

非集合類對象(NSString,NSMutableString,NSData,NSNumber...)的copy 和 mutableCopy

NSString *str1 = @"imutable";? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

NSString *Str2 = [str1 copy];? ? ? ? ? ? ? ? ? ? ? ? ?

NSMutableString *Str3 = [str1 mutableCopy];?

NSMutableString *str4 = [[NSMutableString alloc]initWithString:@"mutable"];

NSMutableString *str5 = [str4 copy];

NSMutableString *str6 = [str4 mutableCopy]; ?

[str6 appendFormat:@"hello"];

[str5 appendFormat:@"hello"]; ? // crash

通過lldb查看變量內存地址,結果如下

總結,非集合類中

1.對 不可變對象 進行 copy ,屬于淺拷貝。

2.對 不可變對象 進行 mutableCopy ,屬于深拷貝

3. 對 可變對象? 進行 copy, 屬于深拷貝

4. 對可變對象進行mutableCopy, 屬于深拷貝

注意:運行到這句 [str5 appendFormat:@"hello"]; 的時候會crash,原因就是 copy 返回的對象是 NSString 對象,然后你用NSMutableString去接受,并調用NSMutableString獨有的 appendFormat 方法。


集合類對象(NSArray,NSDictionary,NSSet...)的copy 和 mutableCopy

NSArray *array0 = @[@"a",@"b",@"c"];

NSArray *array1 = [array0 copy];

NSArray *array2 = [array0 mutableCopy];

NSMutableArray *array3 = [[NSMutableArray alloc]initWithObjects:@"a",@"b",@"c", nil];

NSMutableArray *array4 = [array3 copy];

NSMutableArray *array5 = [array3 mutableCopy];

通過lldb查看變量內存地址,結果如下

總結,在集合類中

1.對不可變對象進行copy,屬于淺拷貝。

2.對不可變對象進行mutableCopy,屬于單層深拷貝

3. 對可變對象進行copy,屬于單層深拷貝

4. 對可變對象進行mutableCopy,屬于單層深拷貝

什么是單層深拷貝?

單層深拷貝是指集合對象的內容復制僅限于對象本身,對象元素仍然是指針復制,例如對 array0 進行? mutableCopy,我們對 array0 進行了內容拷貝,但是array0 里面的元素,我們任然只有指針復制。

@property中copy關鍵字

當我們使用一個copy關鍵字聲明一個對象的時候, 調用 set 方法的時候,copy關鍵字會為對象自動copy一個副本,舉個例子:

@property (nonatomic, copy) NSArray *array;

- (void)setArray:(NSArray *)array {

_array = [array copy]; ?//這里為array ?copy 了一個副本

}

如果我們直接用strong關鍵字的話,又是怎樣的呢?

@property (nonatomic, strong) NSArray *array;

- (void)setArray:(NSArray *)array {

//他們指向了同一塊內存空間,如果此時傳入的array是一個NSMutableArray的話,

//self.array可能會在不知情的情況下被修改。這種情況下面還會再說到

_array = array; ?

}

為什么用@property聲明的NSString(或NSArray,NSDictionary)經常使用copy關鍵字?使用strong關鍵字,會有什么問題?

我們先舉一個例子看看使用strong會有造成什么后果

定義一個以 strong 修飾的 array:

@property (nonatomic , strong) NSArray*array;

.m實現代碼為了方便,我用截圖

總結:

1.因為父類指針可以指向子類對象(如上面的NSArray對象可以指向一個NSMutableArray對象),使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.

2.如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性.

上面解釋了為什么用@property聲明不可變對象(NSString、NSArray,NSDictionary)時,經常用copy關鍵字,接下來我們來解釋為什么要用strong關鍵字來聲明可變對象(NSMutableString、NSMutableArray、NSMutableDictionary),而不用copy對象?

假如我們用copy關鍵字 來聲明一個NSMutableArray對象。

@property (nonatomic, copy) NSMutableArray *mutableArray;

.m實現方法

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@1,@2,nil];

self.mutableArray = array1;

[self.mutableArray removeObjectAtIndex:0]; //crash

上面執行到 removeObjectAtIndex 會crash,原因是 mutableArray 是用copy關鍵字聲明的,copy返回的是一個不可變對象,也就是NSMutableArray會變成NSArray,然后你再執行removeObjectAtIndex方法,就會報找不到這個方法而crash

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容