iOS深淺拷貝的思考

這些天開發(fā)遇到些數(shù)據(jù)拷貝的問題鞋邑,然后在深淺拷貝上?有些迷糊低剔,網(wǎng)上找了些資料,看了半天也不是很明白籍茧,最后決定寫代碼測試一下版述,來加深理解。

先把測試代碼搬上來:

NSMutableString*str1 = [[NSMutableStringalloc]initWithString:@"hello"];

NSString*str2 =@"god";

NSArray*array1 =@[str1,str2];

NSArray*array2 = [array1copy];

NSMutableArray*array3 = [array1mutableCopy];

NSArray*array4 = [[NSArrayalloc]initWithArray:array1];

NSArray*array5 = [[NSArrayalloc]initWithArray:array1copyItems:YES];

NSArray*array6 = [NSKeyedUnarchiverunarchiveObjectWithData:[NSKeyedArchiverarchivedDataWithRootObject:array1]];

先看看array的結(jié)果:


array結(jié)果

從上面結(jié)果可以看出寞冯,copy返回了原結(jié)果渴析,其它的都創(chuàng)建了新的array,所以地址都不一樣吮龄。

再看看str1的結(jié)果:

str1的結(jié)果

從上面的結(jié)果可以看出array1-array4的str1指向的地址是一樣的俭茧,沒有創(chuàng)建新的str,只有array5與array6創(chuàng)建了新的str1漓帚。

然后是str2的結(jié)果:

str1的結(jié)果

可以看出母债,與前面str1有些不同,array1-array5的str2內(nèi)容一樣,只有array6創(chuàng)建了新的str2毡们。

對于結(jié)果的思考

對于NSArray迅皇,使用copy返回了array對象本身,并沒有創(chuàng)建新的對象衙熔,所以array2與array1指向了同一段空間登颓。對于MutableCopy與其它創(chuàng)建的方法,返回的NSArray都是新的對象红氯,說明創(chuàng)建方法至少做了一層深拷貝框咙。

再看str1,其是一個NSMutableString對象脖隶。從結(jié)果可以看出扁耐,array1-array4都是一樣的,array2與array1指向同一個array产阱,結(jié)果一樣不奇怪。array3與array4指向的結(jié)果一致块仆,說明MutableCopy與initWithArray在創(chuàng)建對象時只是做了一層深拷貝构蹬,對于NSArray當(dāng)中的對象并沒有做拷貝,而只是將指針指向了他們悔据。對于initWithArray: copyItems:方法庄敛,如果傳入了YES,在拷貝時會對每一個對象發(fā)送拷貝消息科汗,所以會創(chuàng)新一個新的對象藻烤。而對于使用NSKeyedArchiver方法,由于其會先將對象轉(zhuǎn)換成成NSData對象头滔,然后再從NSData當(dāng)中創(chuàng)建新的NSArray怖亭,?由于從NSData無法與現(xiàn)有的對象進行關(guān)聯(lián),所以它在創(chuàng)建時坤检,是真正意義上的深拷貝兴猩,所以的對象都是新創(chuàng)建的。

再對比str2早歇,按理說它的結(jié)果應(yīng)該與str1是一樣的倾芝,但結(jié)果卻不是,區(qū)別在于array5箭跳,其并沒有創(chuàng)建新的對象晨另。其實你看他的類型就能看出端倪來,god是一樣常量字符串谱姓,在內(nèi)存中借尿,其存入的位置與str1是不一樣的,god是不可以變的逝段,所以對于代碼來講垛玻,沒有必須創(chuàng)建新的對象割捅,因為它只能讀取,不能修改帚桩。所以在copyItems時雖然向他發(fā)送了創(chuàng)建新對象的消息亿驾,但其還是將自身返回了。

可以總結(jié)出一點账嚎,對于不可變的對象莫瞬,即使在copyItem傳入了YES時,也不會創(chuàng)建新的對象郭蕉,因為這是沒有必要的疼邀。只有對于那些可變的對象,才會在YES的時候創(chuàng)建新的對象召锈。想到這里旁振,你會發(fā)現(xiàn)這同樣適用于我們之前測試的時候使用的NSArray對象,NSArray也是不可變的涨岁,所以在copy的時候會返回對象本身拐袜,這時可以在上面加一行測試代碼:

NSMutableArray*array7 = [array3 copy];

array3是NSMutableArray對象,其是可變的梢薪。通過測試你可以看到下面的結(jié)果:

可變對象測試

使用copy方法會創(chuàng)建新的對象蹬铺。到這里,其實可以猜出其中的核心了秉撇,除了MutableCopy外甜攀,其他創(chuàng)建新對象的方法都會調(diào)用該對象的copy方法,至于是否會創(chuàng)建新的對象則需要在對象本身的屬性了琐馆。對于不可變對象规阀,其創(chuàng)建新對象沒有意義,copy會返回對象本身啡捶,對于可變的對象姥敛,在copy時則會創(chuàng)建新對象,在拷貝是瞎暑,其它這都可以認(rèn)為是深拷貝彤敛,雖然不可變對象只返回了指針本身,但由于其特性了赌,其還是屬性深拷貝的墨榄。會有什么樣的結(jié)果,則在于其copy方法具體是怎么實現(xiàn)的了勿她。至于MutableCopy袄秩,由于其本身并不是一個通用的方法,所以其內(nèi)部應(yīng)該也沒有再調(diào)用copy方法了,所以其每次都會返回新的對象之剧。

舉一反三

通過上面的分析郭卫,可以知道拷貝是否會創(chuàng)建新的對象,需要知道該對象是否是可變的背稼,在代碼當(dāng)中則需要知道copy方法是如何實現(xiàn)的了贰军。那么對于我們自己創(chuàng)建的對象,我們應(yīng)該如何控制呢蟹肘,如何控制其copy是創(chuàng)建新對象词疼,還是返回本身呢,對于其成員變量是深拷貝呢帘腹,還是淺拷貝贰盗?

控制方法是自定義對象通過實現(xiàn)NSCopying協(xié)議來實現(xiàn),再寫個測試:

自定義測試類

通過在copyWithZone方法不同的實現(xiàn)來控制阳欲。在測試中再添加下面的測試代碼:

MyObject*obj1 = [[MyObjectalloc]init];

obj1.name= str1;

MyObject*obj2 = [obj1copy];

NSArray*array8 =@[obj1];

NSArray*array9 = [[NSArrayalloc]initWithArray:array8];

NSArray*array10 = [[NSArrayalloc]initWithArray:array8copyItems:YES];

MyMutableObject*mObj1 = [[MyMutableObjectalloc]init];

mObj1.sex=@"man";

mObj1.name= str1;

MyMutableObject*mObj2 = [mObj1copy];

NSArray*array11 =@[mObj1];

NSArray*array12 = [[NSArrayalloc]initWithArray:array11];

NSArray*array13 = [[NSArrayalloc]initWithArray:array11copyItems:YES];

運行結(jié)果就不列出來了舵盈,自己可以再試一下,上面的代碼是一個對象是不可以變的胸完,copy會返回本身书释,另外一個是可變的,且上面代碼對其成員也會進行拷貝赊窥,當(dāng)然也可以不拷貝成員,具體根據(jù)需求了狸页。

最后還要補充一點自己經(jīng)常模糊的锨能,iOS當(dāng)中大部分都是指針,像C當(dāng)中是有一個空間來保存這個指針變量的芍耘,對一個對象而言址遇,它的屬性其實是一個指針變量,你可以改變它的指向斋竞,但如果你想對指向?qū)ο蟮膶傩赃M行修改倔约,你就需要使用這個屬性的方法來完成了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坝初,一起剝皮案震驚了整個濱河市浸剩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鳄袍,老刑警劉巖绢要,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拗小,居然都是意外死亡重罪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剿配,“玉大人搅幅,你說我怎么就攤上這事『襞撸” “怎么了茄唐?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長砸讳。 經(jīng)常有香客問我琢融,道長,這世上最難降的妖魔是什么簿寂? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任漾抬,我火速辦了婚禮,結(jié)果婚禮上常遂,老公的妹妹穿的比我還像新娘纳令。我一直安慰自己,他們只是感情好克胳,可當(dāng)我...
    茶點故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布平绩。 她就那樣靜靜地躺著,像睡著了一般漠另。 火紅的嫁衣襯著肌膚如雪捏雌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天笆搓,我揣著相機與錄音性湿,去河邊找鬼。 笑死满败,一個胖子當(dāng)著我的面吹牛肤频,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播算墨,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼宵荒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了净嘀?” 一聲冷哼從身側(cè)響起报咳,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎面粮,沒想到半個月后少孝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡熬苍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年稍走,在試婚紗的時候發(fā)現(xiàn)自己被綠了袁翁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡婿脸,死狀恐怖粱胜,靈堂內(nèi)的尸體忽然破棺而出怠硼,到底是詐尸還是另有隱情击孩,我是刑警寧澤,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布庵芭,位于F島的核電站抑钟,受9級特大地震影響涯曲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜在塔,卻給世界環(huán)境...
    茶點故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一幻件、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛔溃,春花似錦绰沥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至麸塞,卻和暖如春秃臣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哪工。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工甜刻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人正勒。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像傻铣,于是被迫代替她去往敵國和親章贞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容