NSString屬性聲明中的copy和retain區別


前幾天去面試,被問到了NSString屬性聲明中的copy和retain具體區別,對內存計數的影響,汗,當時沒整明白,也沒答出來,只知道NSString一般用copy.

首先做以下幾個變量聲明:

@property (retain, nonatomic) NSString *retainStr;

@property (copy, nonatomic)   NSString *copyStr;

 

@property (retain, nonatomic) NSMutableString *retainMStr;

@property (copy, nonatomic)   NSMutableString *copyMStr;

 

實現代碼如下:

    NSMutableString *mStr = [NSMutableString string];

    [mStr setString:@"我沒變"];

    

    self.retainStr   = mStr;

    self.copyStr     = mStr;

    self.retainMStr = mStr;

    self.copyMStr   = mStr;

    

    NSLog(@"retainStr:%@"self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

    

    [mStr setString:@"我變了"];

    

    NSLog(@"retainStr:%@"self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

 

    NSString *str = @"我來了";//[[NSString alloc] initWithFormat:@"我來了"];//兩種方式都一樣。

    self.retainStr  = str;

    self.copyStr    = str;

    self.retainMStr = [str mutableCopy];

    self.copyMStr   = [str mutableCopy];

 

    NSLog(@"retainStr:%@"self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

    

    str =@"我走了";//[[NSStringalloc] initWithFormat:@"我走了"];//兩種方式都一樣

 

    NSLog(@"retainStr:%@"self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

 

打印結果如下:

2012-10-12 13:53:14.858 StringDemo[1515:11303] retainStr:我沒變

2012-10-12 13:53:14.860 StringDemo[1515:11303] copyStr:我沒變

2012-10-12 13:53:14.861 StringDemo[1515:11303] retainMStr:我沒變

2012-10-12 13:53:14.862 StringDemo[1515:11303] copyMStr:我沒變

2012-10-12 13:53:14.863 StringDemo[1515:11303] 

2012-10-12 13:53:14.864 StringDemo[1515:11303] retainStr:我變了

2012-10-12 13:53:14.865 StringDemo[1515:11303] copyStr:我沒變

2012-10-12 13:53:14.866 StringDemo[1515:11303] retainMStr:我變了

2012-10-12 13:53:14.867 StringDemo[1515:11303] copyMStr:我沒變

2012-10-12 13:53:14.868 StringDemo[1515:11303] 

2012-10-12 13:53:14.869 StringDemo[1515:11303] retainStr:我來了

2012-10-12 13:53:14.869 StringDemo[1515:11303] copyStr:我來了

2012-10-12 13:53:14.870 StringDemo[1515:11303] retainMStr:我來了

2012-10-12 13:53:14.871 StringDemo[1515:11303] copyMStr:我來了

2012-10-12 13:53:14.872 StringDemo[1515:11303] 

2012-10-12 13:53:14.873 StringDemo[1515:11303] retainStr:我來了

2012-10-12 13:53:14.874 StringDemo[1515:11303] copyStr:我來了

2012-10-12 13:53:14.875 StringDemo[1515:11303] retainMStr:我來了

2012-10-12 13:53:14.876 StringDemo[1515:11303] copyMStr:我來了

 

由此可以看出:對源頭是NSMutableString的字符串,retain僅僅是指針引用,增加了引用計數器,這樣源頭改變的時候,用這種retain方式聲明的變量(無論被賦值的變量是可變的還是不可變的),它也會跟着改變;而copy聲明的變量,它不會跟着源頭改變,它實際上是深拷貝。對源頭是NSString的字符串,無論是retain聲明的變量還是copy聲明的變量,當第二次源頭的字符串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指針引用,也就是淺拷貝。

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

其實說白了,對字符串為啥要用這兩種方式?我覺得還是一個安全問題,比如聲明的一個NSString *str變量,然后把一個NSMutableString *mStr變量的賦值給它了,如果要求str跟着mStr變化,那么就用retain;如果str不能跟着mStr一起變化,那就用copy。而對於要把NSString類型的字符串賦值給str,那兩都沒啥區別。不會影響安全性,內存管理也一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM