2012-03-29 57 views
0

iOS的內存管理是否有從編譯器方面有關的NSString

NSString * str = @"123"; 

NSString * str = [[NSString alloc] initWithString:@"123"]; 

之間有什麼不同?

回答

4

理論上是的;在實現細節中,可能不是。

在第一種情況下,編譯器創建一個常量字符串並將其指向變量str。你不擁有字符串。

在第二種情況下,編譯器創建一個常量字符串(與以前一樣),但這次它被運行時用作初始化您擁有的另一個字符串的參數(因爲第二個字符串是使用alloc創建的) 。

這就是你要知道需要的東西的結尾。

但是,有很多優化繼續。因爲NSStrings是不可變的,所以你會發現initWithString:實際上只是返回參數。通常情況下,它會在返回給你之前保留參數(因爲你期望擁有它),但是字面上的字符串有一個特殊的retainCount(我認爲是INT_MAX),用來停止試圖釋放它們的運行時間。所以在實踐中,你的第二行代碼產生與第一行相同的結果。

順便說一句,這就是爲什麼它不正確的頂部說在第一種情況下字符串是autoreleased,因爲它不是。它只是一個具有特殊保留計數的常量字符串。

但是,您可以也應該安全地忽略實現細節並記住,在第一種情況下您不擁有該字符串,但在第二種情況下您確實擁有該字符串。

+0

+1非常好的答案 – Saphrosit 2012-03-29 11:10:21

1

是的,在第一種情況下,你不擁有該字符串,你不負責釋放它。

在第二種情況下,您調用的是alloc,因此您將成爲該對象的所有者,並且在完成後您必須調用release,否則它將成爲內存泄漏。一般而言,如果您用來獲取對象的方法包含「新」,「分配」,「複製」或「mutableCopy」,那麼您就是對象的所有者,您有責任將其釋放。

檢查memory management rules

0

是的。第一個是NSString的賦值,第二個是alloc(這意味着你需要稍後以某種方式釋放它),並且initWithString:方法被調用。

2

很多差異。最重要的是,您擁有第二個字符串,因此您必須負責釋放它(無論何時從init方法中獲得對象時都是如此)。

另一個是前者創建一個字符串文字,如果你用相同的文字創建一個新的字符串,它們將指向同一個對象。如果你這樣做:

NSString * str1 = @"123"; 
NSString * str2 = [[NSString alloc] initWithString:@"123"]; 
NSString * str3 = @"123"; 

然後str1 == str2是假的,但str1 == str3是真實的。 (當然,字符串的內容是相同的,所以isEqual:將返回true,並且,雖然這確實可以加快比較,但你可能不應該使用它,因爲它是一個實現細節,將來在理論上可能會發生變化)。

+0

'str1 == str2'很可能是真的,但僅僅是因爲實現細節。 – bbum 2012-03-29 17:12:25

0

是的,第一條語句創建一個autorelease對象。 第二個創建佔用一些內存的對象,你必須在使用它之後釋放它。

+3

在第一種情況下,常量字符串不是自動發佈的。 – JeremyP 2012-03-29 10:58:39

+0

好吧,它不是自動回覆。但是,如果它將是 NSString * str = [NSString StringWithString:@「123」]; 那麼它一定是自動釋放的權利? – 2012-04-03 10:21:06

+0

也許,也許不是。由於@「123」是不可變的,所以你可能只會得到一個指向它的指針。 – JeremyP 2012-04-03 10:23:47

0

約內存(你的問題的標題)主重要的區別是: 當你這樣做:

NSString* myString = @"my text"; 

你分配NSConstantString類型的對象。

用的NSString的區別是: NSConstantString是靜態分配,而的NSString是動態分配

+0

差不多;實際上,'str'最終會引用靜態分配的字符串作爲實現細節。 'initWithString:'會看到'@「123」'是一個不可變的字符串,並且會簡單地返回它。 – bbum 2012-03-29 17:11:53