iOS中copy,strong,retain,weak和assign的區(qū)別

本文邏輯圖:

文章邏輯圖

在知道他們區(qū)別之前勋篓,我們首先要知道NSObject對(duì)象的賦值操作做了哪些操作吧享。

A=C其實(shí)是在內(nèi)存中創(chuàng)建了一個(gè)A,然后又開辟了一個(gè)內(nèi)存C譬嚣,C里面存放的著值B钢颂。


NSObject賦值示意圖1

如下:

NSMutableString*tempMStr = [[NSMutableString alloc]initWithString:@"strValue"];
NSLog(@"tempMStr值地址:%p,tempMStr值%@,tempMStr值引用計(jì)數(shù)%@\\n", tempMStr,tempMStr,[tempMStr valueForKey:@"retainCount"]);

//輸出tempMStr值地址:0x7a05f650拜银,tempMStr值strValue,tempMStr值引用計(jì)數(shù)1

此處tempMStr就是A殊鞭,值地址就是C,“strValue”就是B尼桶,而引用計(jì)數(shù)這個(gè)概念是針對(duì)C的操灿,賦值給其他變量或者指針設(shè)置為nil,如tempStr = nil泵督,都會(huì)使得引用計(jì)數(shù)有所增減趾盐。當(dāng)內(nèi)存區(qū)域引用計(jì)數(shù)為0時(shí)就會(huì)將數(shù)據(jù)抹除。而我們使用copy,strong,retain,weak,assign區(qū)別就在:

1.是否開辟新的內(nèi)存
2.是否對(duì)地址C有引用計(jì)數(shù)增加

需要注意的是property修飾符是在被賦值時(shí)起作用幌蚊。

1.以典型的NSMutableString為例

@property(copy,nonatomic)NSMutableString*aCopyMStr;
@property(strong,nonatomic)NSMutableString*strongMStr;
@property(weak,nonatomic)NSMutableString*weakMStr;
@property(assign,nonatomic)NSMutableString*assignMStr;

NSMutableString*mstrOrigin = [[NSMutableStringalloc]initWithString:@"mstrOriginValue"];

self.aCopyMStr= mstrOrigin;
self.strongMStr= mstrOrigin;
self.strongMStr= mstrOrigin;
self.weakMStr= mstrOrigin;

NSLog(@"mstrOrigin輸出:%p,%@\\n", mstrOrigin,mstrOrigin);
NSLog(@"aCopyMStr輸出:%p,%@\\n",_aCopyMStr,_aCopyMStr);
NSLog(@"strongMStr輸出:%p,%@\\n",_strongMStr,_strongMStr);
NSLog(@"weakMStr輸出:%p,%@\\n",_weakMStr,_weakMStr);
NSLog(@"引用計(jì)數(shù)%@",[mstrOriginvalueForKey:@"retainCount"]);

//輸出結(jié)果
//2016-09-01 15:19:13.134 lbCopy[1205:87583] mstrOrigin輸出:0x7892a5e0,mstrOriginValue
//2016-09-01 15:19:13.135 lbCopy[1205:87583] aCopyMStr輸出:0x7893deb0,mstrOriginValue
//2016-09-01 15:19:13.135 lbCopy[1205:87583] strongMStr輸出:0x7892a5e0,mstrOriginValue
//2016-09-01 15:19:13.135 lbCopy[1205:87583] weakMStr輸出:0x7892a5e0,mstrOriginValue
//2016-09-01 15:19:13.135 lbCopy[1205:87583] 引用計(jì)數(shù)2

strongMStr和weakMStr指針指向的內(nèi)存地址都和mstrOrigin相同,但mstrOrigin內(nèi)存引用計(jì)數(shù)為2谤碳,不為3,因?yàn)閣eakMStr雖然指向了數(shù)據(jù)內(nèi)存地址(之后用C簡(jiǎn)稱溢豆,見示意圖1),但不會(huì)增加C計(jì)數(shù)瘸羡。copy修飾的的aCopyMStr漩仙,賦值后則是自己?jiǎn)为?dú)開辟了一塊內(nèi)存,內(nèi)存上保存“mstrOrigin”字符串犹赖,并指向队他。

拷貝示意圖如下


NSMutableString拷貝示意圖2

可見當(dāng)我修改mstrOrigin的值的時(shí)候,必然不會(huì)影響aCopyMStr,只會(huì)影響strongMStr和weakMStr峻村。我們來驗(yàn)證下

NSLog(@"------------------修改原值后------------------------");

[mstrOriginappendString:@"1"];
NSLog(@"mstrOrigin輸出:%p,%@\\n", mstrOrigin,mstrOrigin);
NSLog(@"aCopyMStr輸出:%p,%@\\n",_aCopyMStr,_aCopyMStr);
NSLog(@"strongMStr輸出:%p,%@\\n",_strongMStr,_strongMStr);
NSLog(@"weakMStr輸出:%p,%@\\n",_weakMStr,_weakMStr);

//輸出結(jié)果
//2016-09-01 15:33:02.839 lbCopy[1205:87583] mstrOrigin輸出:0x7892a5e0,mstrOrigin1
//2016-09-01 15:33:02.839 lbCopy[1205:87583] aCopyMStr輸出:0x7893deb0,mstrOrigin
//2016-09-01 15:33:02.839 lbCopy[1205:87583] strongMStr輸出:0x7892a5e0,mstrOrigin1
//2016-09-01 15:33:02.839 lbCopy[1205:87583] weakMStr輸出:0x7892a5e0,mstrOrigin1

copy會(huì)重新開辟新的內(nèi)存來保存一份相同的數(shù)據(jù)麸折。被賦值對(duì)象和原值修改互不影響。strong和weak賦值都指向原來數(shù)據(jù)地址粘昨,區(qū)別是前者會(huì)對(duì)數(shù)據(jù)地址進(jìn)行引用計(jì)數(shù)+1垢啼,后者不會(huì)

引用計(jì)數(shù)是否+1有什么實(shí)質(zhì)區(qū)別呢窜锯?

如果知道“值地址的引用計(jì)數(shù)為0時(shí),地址上保存的值就會(huì)被釋放”芭析。那么區(qū)別就不難理解锚扎,weak修飾的指針A指向的值地址C,那么地址上當(dāng)其他指向他的指針被釋放的時(shí)候馁启,這個(gè)值地址引用計(jì)數(shù)也就變?yōu)?了驾孔,這個(gè)A的值也就為nil了。換句話說當(dāng)值地址C上沒有其他強(qiáng)引用指針修飾的時(shí)候C就會(huì)被立即釋放惯疙,A的值就變?yōu)閚il了翠勉。

這里我們來初始化mstrOrigin和并將strongMStr設(shè)置為nil讓C的引用計(jì)數(shù)為0,然后輸出weakMStr霉颠,看是否為nil.
注:初始化和設(shè)為nil都可以將指針?biāo)赶虻臄?shù)據(jù)地址引用計(jì)數(shù)減少1

mstrOrigin = [[NSMutableStringalloc]initWithString:@"mstrOriginChange2"];
self.strongMStr=nil;
NSLog(@"mstrOrigin輸出:%p,%@\\n", mstrOrigin,mstrOrigin);
NSLog(@"strongMStr輸出:%p,%@\\n",_strongMStr,_strongMStr);
NSLog(@"weakMStr輸出:%p,%@\\n",_weakMStr,_weakMStr);

輸出結(jié)果
//2016-09-01 15:41:33.793 lbCopy[1247:100742] mstrOrigin輸出:0x7874d140,mstrOriginChange2
//2016-09-01 15:41:33.793 lbCopy[1247:100742] strongMStr輸出:0x0,(null)
//2016-09-01 15:41:33.794 lbCopy[1247:100742] weakMStr輸出:0x0,(null)

可見之前引用計(jì)數(shù)2是mstrOrigin和strongMStr添加的对碌。
結(jié)論:copy會(huì)重新開辟新的內(nèi)存來保存一份相同的數(shù)據(jù)。被賦值對(duì)象和原值修改互不影響掉分。strong和weak雖然都指向原來數(shù)據(jù)地址俭缓,原值修改的時(shí)候storng和weak會(huì)隨之變化。區(qū)別是前者會(huì)對(duì)數(shù)據(jù)地址進(jìn)行引用計(jì)數(shù)+1防止原地址值被釋放酥郭,但后者不會(huì)华坦,當(dāng)其他值都不在指向值地址時(shí),值地址被釋放不从,weak的值也就是為nil了惜姐。我們稱會(huì)對(duì)數(shù)據(jù)地址增加引用計(jì)數(shù)的為強(qiáng)引用,不改變引用計(jì)數(shù)的為弱引用

1.2 assign和weak的區(qū)別

對(duì)assign和weak修飾的值進(jìn)行賦值椿息,并輸出指針結(jié)構(gòu)地址和值

self.assignMStr= mstrOrigin;
self.weakMStr= mstrOrigin;
mstrOrigin = [[NSMutableStringalloc]initWithString:@"mstrOriginChange3"];
NSLog(@"weakMStr輸出:%p,%@\\n",_weakMStr,_weakMStr);
NSLog(@"assignMStr輸出:%p,%@\\n",self.assignMStr,self.assignMStr);

可以發(fā)現(xiàn)在輸出assignMStr時(shí)會(huì)偶爾出現(xiàn)奔潰的情況歹袁。原因是發(fā)送了野指針的情況。assign同weak寝优,指向C并且計(jì)數(shù)不+1条舔,但當(dāng)C地址引用計(jì)數(shù)為0時(shí),assign不會(huì)對(duì)C地址進(jìn)行B數(shù)據(jù)的抹除操作乏矾,只是進(jìn)行值釋放孟抗。這就導(dǎo)致野指針存在,即當(dāng)這塊地址還沒寫上其他值前钻心,能輸出正常值凄硼,但一旦重新寫上數(shù)據(jù),該指針隨時(shí)可能沒有值捷沸,造成奔潰摊沉。

1.3那retain是什么

ARC之前屬性構(gòu)造器的關(guān)鍵字是retain,copy,assign,strong和weak是ARC帶出來的關(guān)鍵字痒给。
retain現(xiàn)在同strong说墨,就是指針指向值地址骏全,同時(shí)進(jìn)行引用計(jì)數(shù)加1。

2.非NSMutableString的情況

<br />
上面我們討論了典型的例子NSMutableString婉刀,即非容器可變變量吟温。也就是說還存在其他三種類型需要討論...

1.非容器不可變變量NSSting
2.容器可變變量NSMutableArray
3.容器不可變變量NSArray

更重要的是不同類型會(huì)有不同結(jié)果...,好吧突颊,不要奔潰鲁豪,上面一大段我們討論了1/4,接下來我們要討論其他的3/4情況律秃。但好消息是爬橡,其他幾種情況基本與上面非容器可變變量情況基本類似。

2.1容器可變變量

容器可變變量的典型例子就是NSMutableArray
下面代碼可以忽略棒动,只做參考用

@property(copy,nonatomic)NSMutableArray*aCopyMArr;
@property(strong,nonatomic)NSMutableArray*strongMArr;
@property(weak,nonatomic)NSMutableArray*weakMArr;

NSMutableArray*mArrOrigin = [[NSMutableArrayalloc]init];
NSMutableString*mstr1 = [[NSMutableStringalloc]initWithString:@"value1"];
NSMutableString*mstr2 = [[NSMutableStringalloc]initWithString:@"value2"];
NSMutableString*mstr3 = [[NSMutableStringalloc]initWithString:@"value3"];

[mArrOriginaddObject:mstr1];
[mArrOriginaddObject:mstr2];

//將mArrOrigin拷貝給aCopyMArr糙申,strongMArr,weakMArr
self.aCopyMArr= mArrOrigin;
self.strongMArr= mArrOrigin;
self.weakMArr= mArrOrigin;

NSLog(@"mArrOrigin輸出:%p,%@\\n", mArrOrigin,mArrOrigin);
NSLog(@"aCopyMArr輸出:%p,%@\\n",_aCopyMArr,_aCopyMArr);
NSLog(@"strongMArr輸出:%p,%@\\n",_strongMArr,_strongMArr);
NSLog(@"weakMArr輸出:%p,%@\\n",_weakMArr,_weakMArr);
NSLog(@"weakMArr輸出:%p,%@\\n",_weakMArr[0],_weakMArr[0]);
NSLog(@"mArrOrigin中的數(shù)據(jù)引用計(jì)數(shù)%@", [mArrOriginvalueForKey:@"retainCount"]);
NSLog(@"%p %p %p %p",&mArrOrigin,mArrOrigin,mArrOrigin[0],mArrOrigin[1]);

//以下是輸出
2016-09-02 20:42:30.777 lbCopy[4207:475091] mArrOrigin輸出:0x78f81680,(
value1,
value2
)
2016-09-02 20:42:30.777 lbCopy[4207:475091] aCopyMArr輸出:0x7a041340,(
value1,
value2
)
2016-09-02 20:42:30.777 lbCopy[4207:475091] strongMArr輸出:0x78f81680,(
value1,
value2
)
2016-09-02 20:42:30.777 lbCopy[4207:475091] weakMArr輸出:0x78f81680,(
value1,
value2
)
2016-09-02 20:42:30.777 lbCopy[4207:475091] weakMArr輸出:0x78f816a0,value1
2016-09-02 20:42:30.778 lbCopy[4207:475091] mArrOrigin中的數(shù)據(jù)引用計(jì)數(shù)(
3,
3
)
2016-09-02 20:42:30.778 lbCopy[4207:475091] 0xbffb4098 0x78f81680 0x78f816a0 0x78f81710
//以上是輸出

//給原數(shù)組添加一個(gè)元素
[mArrOriginaddObject:mstr3];

NSLog(@"mArrOrigin輸出:%p,%@\\n", mArrOrigin,mArrOrigin);
NSLog(@"aCopyMArr輸出:%p,%@\\n",_aCopyMArr,_aCopyMArr);
NSLog(@"strongMArr輸出:%p,%@\\n",_strongMArr,_strongMArr);
NSLog(@"weakMArr輸出:%p,%@\\n",_weakMArr,_weakMArr);
NSLog(@"mArrOrigin中的數(shù)據(jù)引用計(jì)數(shù)%@", [mArrOriginvalueForKey:@"retainCount"]);

//修改原數(shù)組中的元素船惨,看是否有隨之變化
[mstr1appendFormat:@"aaa"];

NSLog(@"mArrOrigin輸出:%p,%@\\n", mArrOrigin,mArrOrigin);
NSLog(@"aCopyMArr輸出:%p,%@\\n",_aCopyMArr,_aCopyMArr);
NSLog(@"strongMArr輸出:%p,%@\\n",_strongMArr,_strongMArr);
NSLog(@"weakMArr輸出:%p,%@\\n",_weakMArr,_weakMArr);

//以下是輸出
2016-09-02 20:42:30.778 lbCopy[4207:475091] mArrOrigin輸出:0x78f81680,(
value1,
value2,
value3
)
2016-09-02 20:42:30.778 lbCopy[4207:475091] aCopyMArr輸出:0x7a041340,(
value1,
value2
)
2016-09-02 20:42:30.778 lbCopy[4207:475091] strongMArr輸出:0x78f81680,(
value1,
value2,
value3
)

2016-09-02 20:42:30.778 lbCopy[4207:475091] weakMArr輸出:0x78f81680,(
value1,
value2,
value3
)
2016-09-02 20:42:30.779 lbCopy[4207:475091] mArrOrigin中的數(shù)據(jù)引用計(jì)數(shù)(
3,
3,
2
)
2016-09-02 20:42:30.779 lbCopy[4207:475091] mArrOrigin輸出:0x78f81680,(
value1aaa,
value2,
value3
)
2016-09-02 20:42:30.779 lbCopy[4207:475091] aCopyMArr輸出:0x7a041340,(
value1aaa,
value2
)
2016-09-02 20:42:30.779 lbCopy[4207:475091] strongMArr輸出:0x78f81680,(
value1aaa,
value2,
value3
)
2016-09-02 20:42:30.779 lbCopy[4207:475091] weakMArr輸/出:0x78f81680,(
value1aaa,
value2,
value3
)
//以上是輸出

上面代碼有點(diǎn)多柜裸,所做的操作是mArrOrigin(value1,value2)賦值給copy,strong,weak修飾的aCopyMArr,strongMArr,weakMArr。通過給原數(shù)組增加元素粱锐,修改原數(shù)組元素值疙挺,然后輸出mArrOrigin的引用計(jì)數(shù),和數(shù)組地址怜浅,查看變化铐然。
發(fā)現(xiàn)其中數(shù)組本身指向的內(nèi)存地址除了aCopyMArr重新開辟了一塊地址,strongMArr,weakMArr和mArrOrigin指針指向的地址是一樣的恶座。也就是說

容器可變變量中容器本身和非容器可變變量是一樣的搀暑,copy深拷貝,strongMArr,weakMArr和assign都是淺拷貝

另外我們發(fā)現(xiàn)被拷貝對(duì)象mArrOrigin中的數(shù)據(jù)引用計(jì)數(shù)居然不是1而是3跨琳。也就是說容器內(nèi)的數(shù)據(jù)拷貝都是進(jìn)行了淺拷貝自点。同時(shí)當(dāng)我們修改數(shù)組中的一個(gè)數(shù)據(jù)時(shí)strongMArr,weakMArr,aCopyMArr中的數(shù)據(jù)都改變了脉让,說明

容器可變變量中的數(shù)據(jù)在拷貝的時(shí)候都是淺拷貝

容器可變變量的拷貝結(jié)構(gòu)如下圖

NSMutableArray拷貝示意圖3

2.2非容器不變變量

典型例子是NSString

我們還是以代碼引出結(jié)果

@property(copy,nonatomic)NSString*aCopyStr;
@property(strong,nonatomic)NSString*strongStr;
@property(weak,nonatomic)NSString*weakStr;
@property(assign,nonatomic)NSString*assignStr;

NSLog(@"\\n\\n\\n\\n------------------不可變量實(shí)驗(yàn)------------------------");

NSString*strOrigin = [[NSStringalloc]initWithUTF8String:"strOrigin0123456"];

self.aCopyStr= strOrigin;

self.strongStr= strOrigin;

self.weakStr= strOrigin;

NSLog(@"strOrigin輸出:%p,%@\\n", strOrigin,strOrigin);

NSLog(@"aCopyStr輸出:%p,%@\\n",_aCopyStr,_aCopyStr);

NSLog(@"strongStr輸出:%p,%@\\n",_strongStr,_strongStr);

NSLog(@"weakStr輸出:%p,%@\\n",_weakStr,_weakStr);

NSLog(@"------------------修改原值后------------------------");

strOrigin =@"aaa";

NSLog(@"strOrigin輸出:%p,%@\\n", strOrigin,strOrigin);

NSLog(@"aCopyStr輸出:%p,%@\\n",_aCopyStr,_aCopyStr);

NSLog(@"strongStr輸出:%p,%@\\n",_strongStr,_strongStr);

NSLog(@"weakStr輸出:%p,%@\\n",_weakStr,_weakStr);

NSLog(@"------------------結(jié)論------------------------");

NSLog(@"strOrigin值值為改變樟氢,但strOrigin和aCopyStr指針地址和指向都已經(jīng)改變,說明不可變類型值不可被修改侠鳄,重新初始化");

self.aCopyStr=nil;

self.strongStr=nil;

NSLog(@"strOrigin輸出:%p,%@\\n", strOrigin,strOrigin);

NSLog(@"aCopyStr輸出:%p,%@\\n",_aCopyStr,_aCopyStr);

NSLog(@"strongStr輸出:%p,%@\\n",_strongStr,_strongStr);

NSLog(@"weakStr輸出:%p,%@\\n",_weakStr,_weakStr);

NSLog(@"------------------結(jié)論------------------------");

NSLog(@"當(dāng)只有weakStr擁有C時(shí),值依舊會(huì)被釋放死宣,同非容器可變變量");


//以下是輸出

------------------不可變量實(shí)驗(yàn)------------------------

2016-09-02 21:08:44.053 lbCopy[4297:488549] strOrigin輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.053 lbCopy[4297:488549] aCopyStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.054 lbCopy[4297:488549] strongStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.054 lbCopy[4297:488549] weakStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.054 lbCopy[4297:488549] strOrigin值內(nèi)存引用計(jì)數(shù)3

2016-09-02 21:08:44.054 lbCopy[4297:488549] ------------------修改原值后------------------------

2016-09-02 21:08:44.054 lbCopy[4297:488549] strOrigin輸出:0x8c1f8,aaa

2016-09-02 21:08:44.054 lbCopy[4297:488549] aCopyStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.054 lbCopy[4297:488549] strongStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.055 lbCopy[4297:488549] weakStr輸出:0x7a2550d0,strOrigin0123456

2016-09-02 21:08:44.055 lbCopy[4297:488549] ------------------結(jié)論------------------------

2016-09-02 21:08:44.055 lbCopy[4297:488549] strOrigin值值為改變伟恶,但strOrigin和aCopyStr指針地址和指向都已經(jīng)改變,說明不可變類型值不可被修改毅该,重新初始化

2016-09-02 21:08:44.059 lbCopy[4297:488549] strOrigin輸出:0x8c1f8,aaa

2016-09-02 21:08:44.059 lbCopy[4297:488549] aCopyStr輸出:0x0,(null)

2016-09-02 21:08:44.060 lbCopy[4297:488549] strongStr輸出:0x0,(null)

2016-09-02 21:08:44.060 lbCopy[4297:488549] weakStr輸出:0x0,(null)

2016-09-02 21:08:44.060 lbCopy[4297:488549] ------------------結(jié)論------------------------

2016-09-02 21:08:44.061 lbCopy[4297:488549]當(dāng)只有weakStr擁有C時(shí)博秫,值依舊會(huì)被釋放潦牛,同非容器可變變量
//以上是輸出

此處我們將strOrigin拷貝給aCopyStr,strongStr挡育,weakStr巴碗,然后輸出他們的值地址,發(fā)現(xiàn)他們四個(gè)的值地址一樣即寒,且strOrigin值的引用計(jì)數(shù)為3橡淆。修改strOrigin和發(fā)現(xiàn)strOrigin值地址改變,其他三個(gè)值地址不變母赵,將aCopyStr逸爵,strongStr設(shè)為nil后,發(fā)現(xiàn)weakStr隨之nil凹嘲。

綜合上面現(xiàn)象NSString和NSMutableString(非容器可變變量)基本相同师倔,除了copy,NSString為淺拷貝周蹭,NSMutableString是深拷貝趋艘。那么為什么NSString的copy是淺拷貝呢,也就是說為什么aCopyStr不自己開辟一個(gè)獨(dú)立的內(nèi)存出來呢凶朗。答案很簡(jiǎn)單瓷胧,因?yàn)椴豢勺兞康闹挡粫?huì)改變,既然都不會(huì)改變俱尼,所以沒必要重新開辟一個(gè)內(nèi)存出來讓aCopyStr指向他抖单,直接指向原來值位置就可以了。示意圖如下

NSString拷貝示意圖4

所以非容器不可變量除了copy其他特性同非容器可變變量遇八,copy是淺拷貝

2.3不可變?nèi)萜髯兞?/h3>

典型對(duì)象NSArray矛绘。該對(duì)象實(shí)驗(yàn)自行實(shí)驗(yàn)。但結(jié)論在這里給出刃永,其實(shí)不實(shí)驗(yàn)也可以大概知道概率
在不可變?nèi)萜髯兞恐谢醢萜鞅旧矶际菧\拷貝包括copy,同NSString斯够,容器里面的數(shù)據(jù)都是淺拷貝囚玫,同NSMutableArray。

3.總結(jié)
copy读规,strong抓督,weak,assign的區(qū)別束亏。

可變變量中铃在,copy是重新開辟一個(gè)內(nèi)存,strong,weak定铜,assgin后三者不開辟內(nèi)存阳液,只是指針指向原來保存值的內(nèi)存的位置,storng指向后會(huì)對(duì)該內(nèi)存引用計(jì)數(shù)+1揣炕,而weak帘皿,assgin不會(huì)。weak畸陡,assgin會(huì)在引用保存值的內(nèi)存引用計(jì)數(shù)為0的時(shí)候值為空鹰溜,并且weak會(huì)將內(nèi)存值設(shè)為nil,assign不會(huì)罩锐,assign在內(nèi)存沒有被重寫前依舊可以輸出奉狈,但一旦被重寫將出現(xiàn)奔潰

不可變變量中,因?yàn)橹当旧聿豢杀桓淖兩螅琧opy沒必要開辟出一塊內(nèi)存存放和原來內(nèi)存一模一樣的值仁期,所以內(nèi)存管理系統(tǒng)默認(rèn)都是淺拷貝。其他和可變變量一樣竭恬,如weak修飾的變量同樣會(huì)在內(nèi)存引用計(jì)數(shù)為0時(shí)變?yōu)閚il跛蛋。

容器本身遵守上面準(zhǔn)則,但容器內(nèi)部的每個(gè)值都是淺拷貝痊硕。

**綜上所述赊级,當(dāng)創(chuàng)建property構(gòu)造器創(chuàng)建變量value1的時(shí)候,使用copy岔绸,strong理逊,weak,assign根據(jù)具體使用情況來決定盒揉。value1 = value2晋被,如果你希望value1和value2的修改不會(huì)互相影響的就用用copy,反之用strong,weak,assign刚盈。如果你還希望原來值C(C是什么見示意圖1)為nil的時(shí)候羡洛,你的變量不為nil就用strong,反之用weak和assign。weak和assign保證了不強(qiáng)引用某一塊內(nèi)存藕漱,如delegate我們就用weak表示欲侮,就是為了防止循環(huán)引用的產(chǎn)生。
另外肋联,我們上面討論的是類變量威蕉,直接創(chuàng)建局部變量默認(rèn)是Strong修飾
**

補(bǔ)充:delegate為什么要用weak或者assign而不用strong

a創(chuàng)建對(duì)象b,b中有C類對(duì)象c,所以a對(duì)b有一個(gè)引用,b對(duì)c有一個(gè)引用橄仍,a.b引用計(jì)數(shù)分別為1忘伞,1。當(dāng)c.delegate = b的時(shí)候,實(shí)則是對(duì)b有了一個(gè)引用氓奈,如果此時(shí)c的delegate用strong修飾則會(huì)對(duì)b的值內(nèi)存引用計(jì)數(shù)+1,b引用計(jì)數(shù)為2鼎天。當(dāng)a的生命周期結(jié)束舀奶,隨之釋放對(duì)b的引用,b的引用計(jì)數(shù)變?yōu)?斋射,導(dǎo)致b不能釋放育勺,b不能釋放又導(dǎo)致b對(duì)c的引用不能釋放,c引用計(jì)數(shù)還是為1罗岖,這樣就造成了b和c一直留在了內(nèi)存中涧至。

而要解決這個(gè)問題就是使用weak或者assign修飾delegate,這樣雖然會(huì)有c仍然會(huì)對(duì)b有一個(gè)引用桑包,但是引用是弱引用南蓬,當(dāng)a生命周期結(jié)束的時(shí)候,b的引用計(jì)數(shù)變?yōu)?哑了,b釋放后隨之c的引用消失赘方,c引用計(jì)數(shù)變?yōu)?,釋放弱左。

不可變常量的特殊性

在2.2的討論中如果你
1.字符串改成小于10長(zhǎng)度的字符串
2.NSString*strOrigin = @"strOrigin0123456";
初始化NSString窄陡,你都會(huì)發(fā)現(xiàn)strOrigin值內(nèi)存引用計(jì)數(shù)將發(fā)生異常,通常表現(xiàn)為引用計(jì)數(shù)特別大拆火,具體可以看下iOS中NSString的特別之處這篇文章

項(xiàng)目地址https://github.com/ai966669/copy

交流qq:578172874

錯(cuò)誤之處希望能幫忙提出來跳夭,O(∩_∩)O謝謝了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市们镜,隨后出現(xiàn)的幾起案子币叹,更是在濱河造成了極大的恐慌,老刑警劉巖憎账,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件套硼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡胞皱,警方通過查閱死者的電腦和手機(jī)邪意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來反砌,“玉大人雾鬼,你說我怎么就攤上這事⊙缡鳎” “怎么了策菜?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我又憨,道長(zhǎng)翠霍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任蠢莺,我火速辦了婚禮寒匙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躏将。我一直安慰自己锄弱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布祸憋。 她就那樣靜靜地躺著会宪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚯窥。 梳的紋絲不亂的頭發(fā)上掸鹅,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音沟沙,去河邊找鬼河劝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛矛紫,可吹牛的內(nèi)容都是我干的赎瞎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼颊咬,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼务甥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喳篇,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤敞临,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后麸澜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挺尿,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年炊邦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了编矾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡馁害,死狀恐怖窄俏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碘菜,我是刑警寧澤凹蜈,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布限寞,位于F島的核電站,受9級(jí)特大地震影響仰坦,放射性物質(zhì)發(fā)生泄漏履植。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一缎岗、第九天 我趴在偏房一處隱蔽的房頂上張望静尼。 院中可真熱鬧,春花似錦传泊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鹃祖,卻和暖如春溪椎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恬口。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工校读, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祖能。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓歉秫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親养铸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子雁芙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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