2012-07-09 80 views
1

因爲我是新的客觀C,所以我在理解內存管理的一個概念時遇到了問題。例如讓我說我有一個Bar和Foo類。從另一個對象返回對象時的客觀c內存管理

在主要功能

我打電話:

Foo *foo = [bar getFoo]; //In my bar method I return foo 
[foo retain]; 
[foo callMethod]; 
[foo release]; 

我知道這是做正確的方式。但是,爲什麼我們必須在從另一個對象獲取它之後保留它,這是否意味着返回的對象保留了計數0?所以我們必須馴化它以計算1使用它?但是如果它的靛子數爲0,我們怎麼知道它仍然存在。我們可以假設,因爲增量保留計數的下一行是對象內存不會被重新定位,但是如果我們有多線程程序呢?

+0

如果您在Xcode 4.2中打開ARC,所有這些廢話都會消失。 – ratbum 2012-07-09 10:08:02

回答

3

當一個類方法返回一個對象時,它將autorelease它,所以你不必打擾;一般:

- (Foo *)getFoo 
{ 
    return [[_foo retain] autorelease]; 
} 

如果你只使用foo的調用方法的壽命,你不需要retain它,因爲它不會autorelease d,直到通過運行循環下一次,讓你的代碼實際上應該是:

Foo *foo = [bar getFoo]; //In my bar method I return foo 
[foo callMethod]; 

但是,如果你想保持foo一會兒,調用方法的範圍之內,你需要retain,然後release它晚些時候。

還有一件事; getter方法名稱的約定只是「名稱」,所以你的設置器應該是setFoo,你的獲取器應該是foo。遵守命名約定是一個好主意,因爲它可以讓你知道一種方法在7個月的時間內做了些什麼,像靜態分析這樣的工具可以理解這些約定。

0

方法getFoo不返回具有0保留計數的對象。它返回一個+ 0的對象保留計數這意味着:

  • 對象的保留計數不爲空(否則,對象將不存在)
  • 並保留計數沒有改變通過調用該方法,或者如果是的話,它是一種平衡的方式(使用盡可能多的release/autorelease作爲retain/alloc/new/copy)。

因此,對象的生命週期完全取決於它在哪裏以及如何保留。我們不知道對象將會有效多長時間,因爲任何方法調用可能會釋放對象

例如,讓我們考慮下面的代碼:

id anObject = [anArray objectAtIndex:0]; 
[anArray removeObjectAtIndex:0];

目的anObject不保留任何更多由陣列,因爲我們除去它。因此它可能已被破壞(但也許並不是因爲它仍然在其他地方使用)。

通常,從方法獲取一個對象時(其它的是alloccopynewretain),我們可以假設:

  • 任一對象被保留,然後自動釋放,
  • 任一對象由返回它的對象保留。

所以我們知道對象foo是有效的,直到我們從當前方法/函數返回或者我們調用的方法/函數,改變對象bar,以先到者爲準的狀態。之後,它可能已經被破壞。

所以在你的情況下,你可以放心地省略retain/release對。

但是,要保證一個對象不會被釋放是非常困難的,除非我們知道我們調用的每個方法的實現。因此,保留(然後釋放)我們得到的每個對象都是更安全的方法,這就是編譯器在啓用ARC(自動引用計數)時將執行的操作。

但是,這將需要你寫很多retain/release和你的代碼會變得難以閱讀,理解和維護。而且,你寫的代碼越多,得到的錯誤就越多(除非你從不寫錯誤)。

總之,除非您有理由懷疑它可能會消失,否則不需要保留一個對象。