1. 程式人生 > >重新理解strong與weak(強引用,弱引用),以及strong和copy的區別

重新理解strong與weak(強引用,弱引用),以及strong和copy的區別

- (void)test:

{

    NSMutableString *mStr = [NSMutableStringstringWithFormat:@"hello"];

    self.sStr   = mStr;

    self.cStr     = mStr;

    NSLog(@"mStr:%p,%p",  mStr,&mStr);

    NSLog(@"strongStr:%p,%p", _sStr, &_sStr);

   NSLog(@"copyStr:%p,%p",   _cStr, &_cStr);

上段程式碼中sStr與mStr指向同樣的地址,他們指向的是同一個物件@“hello

”,這個物件的地址沒變,所以他們的值是一樣的。

當把mStr賦值給copy的cStr時,cStr物件是深複製而來,一個新的物件,這個物件有新的地址不再是原來的地址了

如果現在改變mStr的值:

    [mStr appendString:@"world"];

    NSLog(@"strongStr:%@",  _sStr);

    NSLog(@"copyStr:%@",    _cStr);

結果

使用strong的字串sStr的值:@"helloworld",而使用copy的字串cStr的值:@"hello",

所以,如果一般情況下,我們都不希望字串的值跟著mStr變化,所以我們一般用copy來設定string的屬性。

如果希望字串的值跟著賦值的字串的值變化,可以使用strong,retain。

注意:上面的情況是針對於當把NSMutableString賦值給NSString的時候,才會有不同,如果是賦值是NSString

物件,那麼使用copy還是strong,結果都是一樣的,因為NSString物件根本就不能改變自身的值,他是不可變的。

把一個物件賦值給一個屬性變數,當這個物件變化了,如果希望屬性變數變化就使用strong屬性,如果希望屬性變數不跟著變化,就是用copy屬性。

結論

這裡寫一寫結論引用自別的部落格(http://blog.csdn.net/itianyi/article/details/9018567

對源頭是NSMutableString的字串,retain僅僅是指標引用,增加了引用計數器,這樣源頭改變的時候,用這種retain方式宣告的變數(無論被賦值的變數是可變的還是不可變的),它也會跟著改變;而copy宣告的變數,它不會跟著源頭改變,它實際上是深拷貝。

對源頭是NSString的字串,無論是retain宣告的變數還是copy宣告的變數,當第二次源頭的字串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指標引用,也就是淺拷貝。

另外說明一下,這兩者對記憶體計數的影響都是一樣的,都會增加記憶體引用計數,都需要在最後的時候做處理。

其實說白了,對字串為啥要用這兩種方式?我覺得還是一個安全問題,比如宣告的一個NSString *str變數,然後把一個NSMutableString *mStr變數的賦值給它了,如果要求str跟著mStr變化,那麼就用retain;如果str不能跟著mStr一起變化,那就用copy。而對於要把NSString型別的字串賦值給str,那兩都沒啥區別。不會影響安全性,記憶體管理也一樣。