2011-03-14 30 views
0
NSString *s1 = @"string1"; 
// NSString *s2 = [[NSString alloc]stringWithFormat:@"string2"]; 
NSString *s2 = [[NSString alloc] initWithFormat:@"string2"]; 

我知道這是非常基本的概念,但我不完全清楚這一點。目標C,NSSting與「alloc」並且沒有「alloc」的區別

第一個不分配的內存地址,併發送一個分配的內存地址... 另外第二個增加了變量的引用計數,但不是第一個...... 儘管我理解這個概念,但不知道當我應該使用第一個或第二個的情況..

什麼時候應該使用第一個?還應該什麼時候用第二個?

在此先感謝..

+0

根據John的觀察來修正你的代碼。 – bbum 2011-03-14 05:09:57

回答

4

你不應該使用第二個 - +stringWithFormat:是一個類方法。包括你的第一個例子,你已經基本上3種選擇:

NSString *s1 = @"string1"; 
NSString *s2 = [[NSString alloc] initWithString:@"string2"]; 
NSString *s3 = [NSString stringWithFormat:@"string3"]; 

s1在這種情況下是一個指向一個常量字符串。 s2s3都指向您創建的新字符串,但s2已保留給您,並且s3已被自動發佈。如果您只需要一個臨時對象,則自動釋放對象s3或常量對象s1是不錯的選擇。如果你需要保持字符串,你應該使用s2(實際上,現在我認爲它s1也可以在這種情況下工作 - 但它並不真正習慣)。

通過發送retain消息,您可以使s1s3等效於s2。您也可以通過發送autorelease消息將s2轉換爲等效對象。

+0

非常感謝! – codereviewanskquestions 2011-03-14 04:34:32

1

字符串文字像@"string1"(或第二線的@"string2"),正如你提到的,不分配。字符串實際上是作爲常量存儲在可執行文件的數據部分中的,就像您聲明的任何常量一樣。用這種方式創建的字符串並沒有真正的引用計數。你可以發送-retain-release消息給他們,沒有什麼會發生。

你的第二行是不合格的; +stringWithFormat:實際上是一個類方法,如果沒有任何格式參數,使用+stringWithFormat:並沒有意義。一般來說,只要使用字符串文字形式,如果你沒有特定的理由使用另一種形式。如果您的應用程序中已經存在常量對象,則不需要分配新對象。

1

如果您只是要傳遞一個常量字符串,請不要使用任何...WithFormat:方法。不需要爲平凡的情況分析格式字符串。

+1

更不用說它會導致不必要的分配! – bbum 2011-03-14 05:08:23

8

卡爾是對的,但有一些微妙的記住。試想一下:

NSString *s1 = @"string1"; 
NSString *s2 = [[NSString alloc] initWithString:@"string1"]; 
NSString *s3 = [NSString stringWithString:@"string1"]; 
NSString *s4 = [NSString stringWithFormat:@"string1"]; 

NSLog(@"ptrs %p %p %p %p", s1, s2, s3, s4); 

輸出是:

ptrs 0x1000010c0 0x1000010c0 0x1000010c0 0x100108da0 

這是正確的; s1,s2s3都指向相同的字符串實例,而s4最終成爲新實例。這是因爲NSString可檢測到字符串正在從一個常量字符串初始化時,並且在完全有效的情況下返回常量字符串而不是分配新的內存塊來保存相同的內容。 stringWithFormat:情況可能沒有那麼優化,因爲所有可能的格式字符串處理都使得這樣的優化既沒有實際意義,也可能不自然。

換句話說,做而不是假設兩個字符串只是通過代碼檢查或指針比較相同或不同。使用isEqual:或更好的是isEqualToString:

+0

+1 @bbum ...很好的說明,謝謝! – 2011-03-14 05:09:00