總結(jié)深拷貝淺拷貝的一些問題

本文主要參考:
http://www.reibang.com/p/8080bbae0acc如有侵權(quán)但骨,告知我撤銷道逗。

iOS開發(fā)中砂沛,不是所有的對象都支持copy、mutableCopy哀澈。
遵守NSCopying協(xié)議的類可以發(fā)送copy消息牌借,遵守NSMutableCopying協(xié)議的類才可以發(fā)送mutablecopy消息。
顧名思義日丹,copy就是復(fù)制了一個imutable(非容器類)的對象走哺,而mutablecopy(容器類)就是復(fù)制了一個mutable的對象蚯嫌。

一哲虾、非集合類對象(如NSString、NSNumber)
1择示、非容器類對象(如NSString束凑、NSNumber等一類的對象)


非容器非集合.jpg

總結(jié):對一個iMutable(非容器)的非集合類對象string:
調(diào)copy方法,其實復(fù)制的是string對象指向那塊內(nèi)存地址的指針栅盲,是指針拷貝汪诉,string 和stringCopy都是指向的同一塊內(nèi)存地址。(淺拷貝)
調(diào)mutableCopy方法,復(fù)制的是string對象指向的那塊內(nèi)存地址的內(nèi)容扒寄,是內(nèi)容拷貝鱼鼓,stringMutableCopy重新指向一塊內(nèi)存地址,而這個內(nèi)存地址保存的內(nèi)容是從string指向的內(nèi)存地址復(fù)制過來的,stringMutableCopy是一個可變對象该编。(深拷貝)
2迄本、容器類對象(如NSMutableString、NSMutableNumber等一類的對象)


容器非集合對象.jpg

總結(jié):對一個mutable的非集合類對象mutableString课竣,
調(diào)copy方法嘉赎,復(fù)制的是mutableString對象指向的那塊內(nèi)存地址的內(nèi)容,是內(nèi)容拷貝于樟,但是得到的mutableStringCopy對象是一個不可變對象公条。
調(diào)mutableCopy方法,是內(nèi)容拷貝迂曲,且得到的mutableStringMutableCopy對象是一個可變對象

非集合類總結(jié):在非集合類對象中靶橱,對immutable對象進行copy操作,是指針復(fù)制路捧,mutableCopy操作時內(nèi)容復(fù)制抓韩;對mutable對象進行copy和mutableCopy都是內(nèi)容復(fù)制。用代碼簡單表示如下:
[immutableObject copy] // 淺復(fù)制
[immutableObject mutableCopy] //深復(fù)制
[mutableObject copy] //深復(fù)制
[mutableObject mutableCopy] //深復(fù)制

二鬓长、集合類對象(如NSDictionary谒拴、NSArray、NSSet一類的對象)


非容器集合類.jpg

總結(jié):copy操作進行了指針拷貝涉波,mutableCopy進行了內(nèi)容拷貝英上。但需要強調(diào)的是:此處的內(nèi)容拷貝,僅僅是拷貝array這個對象啤覆,array集合內(nèi)部的元素仍然是指針拷貝苍日。
arrayCopy和array是指針復(fù)制,是同一個NSArray對象(指向相同的對象)窗声,包括array里面的元素也是指向相同的指針
mutableArrayCopy是兌現(xiàn)復(fù)制相恃,是array的可變副本,指向的對象和array不同笨觅。但是其中的元素和array中的元素指向的是同一個對象拦耐。mutableArrayCopy還可以修改自己的對象。
[mutableArrayCopy addObject:@“de”];
[mutableArrayCopy removeObjectAtIndex:0];//注意见剩,容器內(nèi)的元素內(nèi)容都是指針復(fù)制杀糯。


例子.jpg

對于容器,其元素對象始終是指針復(fù)制苍苞。如果需要元素對象也是對象復(fù)制固翰,就需要實現(xiàn)深拷貝:
test.jpg

trueDeepCopyArray是完全意義上的深拷貝,而deepCopyArray則不是,對于deepCopyArray內(nèi)的不可變元素其還是指針復(fù)制骂际×屏穑或者我們自己實現(xiàn)深拷貝的方法。因為如果容器的某一元素是不可變的歉铝,那你復(fù)制完后該對象仍舊是不能改變的没炒,因此只需要指針復(fù)制即可。除非你對容器內(nèi)的元素重新賦值犯戏,否則指針復(fù)制即已足夠送火。舉個例子,[[array objectAtIndex:0] appendstring:@”sd”]后其他的容器內(nèi)對象并不會受影響先匪。[[array objectAtIndex:1]和[[deepCopyArray objectAtIndex:0]盡管是指向同一塊內(nèi)存种吸,但是我們沒有辦法對其進行修改——因為它是不可改變的。所以指針復(fù)制已經(jīng)足夠呀非。


test.jpg

內(nèi)存地址不一樣坚俗,說明對于mutable Array,調(diào)copy和調(diào)mutable方法都是進行內(nèi)容拷貝,array集合內(nèi)部的元素仍然是指針拷貝

二岸裙、自定義對象
當(dāng)然在 ios 中并不是所有的對象都支持copy猖败,mutableCopy,遵守NSCopying協(xié)議的類可以發(fā)送copy消息降允,遵守NSMutableCopying協(xié)議的類才可以發(fā)送mutableCopy消息恩闻。
假如發(fā)送了一個沒有遵守上述兩協(xié)議而發(fā)送copy或者 mutableCopy,那么就會發(fā)生異常。但是默認(rèn)的ios類并沒有遵守這兩個協(xié)議剧董。如果想自定義一下copy那么就必須遵守NSCopying,并且實現(xiàn) copyWithZone:方法幢尚,如果想自定義一下mutableCopy那么就必須遵守NSMutableCopying,并且實現(xiàn) mutableCopyWithZone:方法。
@interface Copy : NSObject<NSCopying,NSMutableCopying>
{
NSMutableString *name;
NSString *imutableStr;
int age;
}
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *imutableStr;
@property (nonatomic) int age;
@end
@implementation Copy
@synthesize name;
@synthesize age;
@synthesize imutableStr;

  • (id)init
    {
    if (self = [super init])
    {
    self.name = [[NSMutableString alloc]init];
    self.imutableStr = [[NSString alloc]init];
    age = -1;
    }
    return self;
    }
  • (void)dealloc
    {
    [name release];
    [imutableStr release];
    [super dealloc];
    }
  • (id)copyWithZone:(NSZone *)zone
    {
    MyObj *copy = [[[self class] allocWithZone:zone] init];
    copy->name = [name copy];
    copy->imutableStr = [imutableStr copy];
    // copy->name = [name copyWithZone:zone];;
    // copy->imutableStr = [name copyWithZone:zone];//
    copy->age = age;
    return copy;
    }
  • (id)mutableCopyWithZone:(NSZone *)zone
    {
    MyObj *copy = NSCopyObject(self, 0, zone);
    copy->name = [self.name mutableCopy];
    copy->age = age;
    return copy;

}
@end
四翅楼。屬性修飾符相關(guān)
如果property是NSString或NSArray及其子類的時候尉剩,最好選擇使用copy。為什么毅臊?
這是為了防止賦值給它的是可變的數(shù)據(jù)理茎,如果可變的數(shù)據(jù)發(fā)生了變化,那么該property也會發(fā)生變化管嬉。

@interface Person : NSObject
@property (strong, nonatomic) NSArray *bookArray1;
@property (copy, nonatomic) NSArray *bookArray2;
@end
@implementation Person
//省略setter方法
@end
//Person調(diào)用
main(){
NSMutableArray *books = [@[@"book1"] mutableCopy];
Person *person = [[Person alloc] init];
person.bookArray1 = books;
person.bookArray2 = books;
[books addObject:@"book2"];
NSLog(@"bookArray1:%@",person.bookArray1);
NSLog(@"bookArray2:%@",person.bookArray2);
}

test.jpg

我們看到皂林,使用strong修飾的person.bookArray1輸出是[book1,book2],而使用copy修飾的person.bookArray2輸出是[book1]宠蚂。這下可以看出來區(qū)別了吧式撼。
備注:使用strong童社,則person.bookArray1與可變數(shù)組books指向同一塊內(nèi)存區(qū)域求厕,books內(nèi)容改變,導(dǎo)致person.bookArray1的內(nèi)容改變,因為兩者是同一個東西呀癣;而使用copy美浦,person.bookArray2在賦值之前,將books內(nèi)容復(fù)制项栏,創(chuàng)建一個新的內(nèi)存區(qū)域浦辨,所以兩者不是一回事,books的改變不會導(dǎo)致person.bookArray2的改變沼沈。
當(dāng)源字符串是NSString時流酬,由于字符串是不可變的,所以列另,不管是strong還是copy屬性的對象芽腾,都是指向源對象,copy操作只是做了次淺拷貝页衙。
當(dāng)源字符串是NSMutableString時摊滔,strong屬性只是增加了源字符串的引用計數(shù),而copy屬性則是對源字符串做了次深拷貝店乐,產(chǎn)生一個新的對象艰躺,且copy屬性對象指向這個新的對象。另外需要注意的是眨八,這個copy屬性對象的類型始終是NSString腺兴,而不是NSMutableString,因此其是不可變的廉侧。

這里還有一個性能問題含长,即在源字符串是NSMutableString,strong是單純的增加對象的引用計數(shù)伏穆,而copy操作是執(zhí)行了一次深拷貝拘泞,所以性能上會有所差異。而如果源字符串是NSString時枕扫,則沒有這個問題陪腌。
所以,在聲明NSString屬性時烟瞧,到底是選擇strong還是copy诗鸭,可以根據(jù)實際情況來定。不過参滴,一般我們將對象聲明為NSString時强岸,都不希望它改變,所以大多數(shù)情況下砾赔,我們建議用copy蝌箍,以免因可變字符串的修改導(dǎo)致的一些非預(yù)期問題

說到底青灼,其實就是不同的修飾符,對應(yīng)不同的setter方法妓盲,
strong對應(yīng)的setter方法杂拨,是將_property先release(_property release),然后將參數(shù)retain(property retain)悯衬,最后是_property = property弹沽。
copy對應(yīng)的setter方法,是將_property先release(_property release)筋粗,然后拷貝參數(shù)內(nèi)容(property copy)策橘,創(chuàng)建一塊新的內(nèi)存地址,最后_property = property娜亿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末役纹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子暇唾,更是在濱河造成了極大的恐慌促脉,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件策州,死亡現(xiàn)場離奇詭異瘸味,居然都是意外死亡,警方通過查閱死者的電腦和手機够挂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門旁仿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人孽糖,你說我怎么就攤上這事枯冈。” “怎么了办悟?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵尘奏,是天一觀的道長。 經(jīng)常有香客問我病蛉,道長炫加,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任铺然,我火速辦了婚禮俗孝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魄健。我一直安慰自己赋铝,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布沽瘦。 她就那樣靜靜地躺著革骨,像睡著了一般农尖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苛蒲,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天卤橄,我揣著相機與錄音绿满,去河邊找鬼臂外。 笑死,一個胖子當(dāng)著我的面吹牛喇颁,可吹牛的內(nèi)容都是我干的漏健。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼橘霎,長吁一口氣:“原來是場噩夢啊……” “哼蔫浆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姐叁,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤瓦盛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后外潜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體原环,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年处窥,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘱吗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡滔驾,死狀恐怖谒麦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哆致,我是刑警寧澤绕德,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站摊阀,受9級特大地震影響迁匠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驹溃,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一城丧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧豌鹤,春花似錦亡哄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愿卸。三九已至,卻和暖如春截型,著一層夾襖步出監(jiān)牢的瞬間趴荸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工宦焦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留发钝,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓波闹,卻偏偏與公主長得像酝豪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子精堕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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

  • 夢里有彩虹和獅子 瀑布 醒來的時候光和風(fēng)晃悠著窗簾 不記得夢里的獅子是撕扯了彩虹還是被瀑布沖走了 只記得它毛色棕紅...
    小海狗_閱讀 195評論 0 0
  • 本文作者Will Little是Code Fellows公司的聯(lián)合創(chuàng)始人兼CEO孵淘。該公司位于西雅圖,它是一家編程學(xué)...
    逝去的榮光閱讀 947評論 2 25
  • 余娜 講師五期 分享第443天 2018.06.15 手表定律的內(nèi)涵是:當(dāng)我們擁有一只手表時歹篓,我們很容易知道現(xiàn)在是...
    小魚公子閱讀 803評論 0 0
  • 1 記得我的高中班主任說起自己的往事庄撮,當(dāng)他在大學(xué)時勤奮刻苦地學(xué)習(xí)時背捌,很多人嘲笑他是書呆子,當(dāng)時正是“讀書無用論”當(dāng)...
    最美的太陽93閱讀 973評論 6 5