2010-03-05 154 views
0

比方說,我做了以下(富開始爲一些對象):釋放和保留

[foo release]; 
// STUFF with foo 
[foo retain]; 

只要我不是重新分配FOO,在此我還是有結束同樣的富,對嗎?我是不是冒着失去foo的風險去冒險?

我想我確定我對版本的理解是正確的。如果我釋放foo,它不會消失,直到它上的所有句柄都消失。換句話說,foo必須被分配給// STUFF中的某個其他對象,否則foo必須超出// STUFF的範圍(並且可能會創建一個新的foo),以便實際使用原始foo要刪除的對象,對嗎?

編輯動機:

我想這樣做是可以說我有以下switch語句的原因:

switch (test) 
{ 
    case 1: 
     foo = [A alloc]; 
     [foo inita]; 
     break; 
    case 2: 
     foo = [B alloc]; 
     [foo initb]; 
     break; 
    case 3: 
     [foo setupc]; 
     break; 
    case 4: 
     f = [D alloc]; 
     [foo initd]; 
     break; 
} 

這是有道理的開關之前釋放foo和在保留它然後結束。情況3除外。所以,我在想,如果按照我的建議安全地做,可能會使代碼變得更簡單。

當然我可以只放了釋放/保留圍繞每個分配/初始化對,但是這是一個很大的重複代碼...

A [富自動釋放],然後保留可能只是做的伎倆。

+0

如果您在這裏提供更多的上下文,這將有所幫助。 foo是一個實例變量,並且假設foo已經在交換機之前包含了一個對象? (否則,爲什麼你需要調用-release?)另外,alloc返回一個保留計數爲1的實例。爲什麼你需要額外的電話保留?我完全不清楚你在這裏做什麼。 – jlehr 2010-03-05 22:31:53

+0

測試的性質是什麼?根據答案,可能會用多態行爲替換交換機。 – outis 2010-03-05 22:44:05

+0

@JLehr,test是一個基於mimetype的int。不同的類型是不同類型的文檔... foo是一個實例變量,它可能已經包含一個對象。 (因此釋放)在情況3的實際代碼中,「if(foo == nil)foo = [C alloc];」在情況3 ...我不確定我是否需要保留。我想我的問題比我想象的要大...... – 2010-03-05 22:49:34

回答

3

不,這裏是發生了什麼:

-release方法遞減保留計數,然後檢查是否它現在是零。如果保留計數爲零,則-release調用[self dealloc],這會導致立即解除分配對象。因此,在發送-retain消息之前發送-release並不是一個好主意,並且可能會導致應用程序崩潰。

根據您添加了註釋,這裏的寫,我想會做你想要什麼,同時避免重複代碼的代碼的另一種方法:

Class class = Nil; 

// Decide which class (if any) to use... 
switch (test) 
{ 
    case 1: class = [A class]; break; 
    case 2: class = [B class]; break; 
    case 3: class = foo == nil ? Nil : [C class]; break; 
    case 4: class = [D class]; break; 
} 

// If a class was selected, create a new instance 
// and release the previous one... 
if (class != Nil) 
{ 
    [foo release]; 
    foo = [[class alloc] init]; 
} 

注意,沒有必要爲一個-retain這裏是因爲我前面提到過,+alloc將保留計數設置爲1。

3

如果foo的保留計數在該代碼的開始處變爲零,則它將被消除並停止工作。如果您想要做那樣的事情,請使用autorelease。根據文檔,release是垃圾收集環境中的一種無用操作 - 也許這就是你的想法?

+0

實際上,你可以保證當它的保留變爲零時它會被消除。 – cobbal 2010-03-05 22:16:02

+0

@cobbal,那是真的。我不想在沒有查看的情況下明確地寫出這些信息。我從那以後發現了我在文檔中查找的行,並且它與您說的(以及我的預期)保持一致。 – 2010-03-05 22:17:51

+0

謝謝,我添加了動力,autorelease爲此工作? – 2010-03-05 22:23:14

0

全部release確實是遞減每個對象具有的引用計數器。

我不確定爲什麼你想要releaseretain像你所示,但。

+0

是的,我增加了動力... – 2010-03-05 22:24:09

0

是的,您最肯定的是在參考計數(非GC)環境中在STUFF期間冒着「失去」的風險。如果您的第一個-releasefoo的引用計數遞減爲0,它將被解除分配。在這種情況下繼續使用foo正冒險進入未定義的行爲,並且您幾乎肯定會最終付出代價。換句話說,這裏有龍。它在可能的情況下的工作,你(和你調用任何其他框架)不會在STUFF分配任何內存,其overrites分配的實例foo引用實例指向foo-dealloc方法不改變foo的狀態,除了釋放實例變量引用,並且破壞那些引用佔用的內存等等。在這種情況下,您的代碼可能的工作方式好像foo未被釋放,但那只是運氣。

在垃圾收集環境中,您是安全的。由於您持有對fooSTUFF的引用,並且由於-release-retain在GC環境中爲空操作,因此foo仍然有效。