autorelease的使用場景

2021-07-31 17:27:33 字數 3014 閱讀 9206

**autorelease 就是把 release 延後到 autorelease pool drain 的時候。**是 arc 進行引用計數管理機制中的一部分,挺巧妙的。其它還有 weak 指標等都是為了管理好記憶體設計的機制。主要是可以用在非 alloc、copy、new等函式的返回值上面。可以對應解決的需求是這些函式內部 retain 了返回值,返回時不能 release,否則呼叫方再拿這個位址訪問就會 bad_access,也不能交給呼叫方去 release,因為沒有約定,你乙個普通函式的返回值,我也不知道你內部 retain了沒有,該不該幫你 release 掉,所以就設計了這麼乙個 autorelease 機制,延後 release,先暫存起來,pool drain 的時候 relase。pool drain 要麼是手動的 autorelease pool 作用域結束,要麼是乙個 runloop 結束。out parmater 也會 autorelase, 不要放到手動 autorelease pool 裡面,防止被**。主要作用是讓物件多活著一段時間,然後穿透作用域邊界等等。使用場景是,我 retain 了乙個物件,我有職責 release 它,但是現在不能的情況。因為我知道後續**可能想要 retain 它 。

考慮這樣乙個場景,我們有個方法返回乙個物件,在方法內部我們 retain 了這個物件,這意味這我們需要 release 這個物件,維持物件引用計數的平衡。但是因為這個物件是返回值,我們要確保呼叫方拿到的物件是沒被**的,在函式返回前 release 的話,我們就不能確保這一點。也就是說,我們需要 release 返回值,但又不能在函式返回前。這時候,我們有兩個選擇。要麼延後 release ,要麼呼叫方幫我們 release。這分別對應著解決函式返回值引用計數問題的兩種方式。

第一種延後 release 就是 autorelease,函式返回前不進行 release ,先把返回值暫存在 autorelease pool 中一段時間。這段時間內,呼叫方如果需要,可以 retain 這個返回值,等到 autorelease pool 幹的時候,再去 release 這個物件,平衡物件引用計數,適用於除 alloc 、copy 、new 、mutablecopy 之外的函式返回值。

第二種是函式呼叫方負責 release 函式返回值,函式和函式呼叫方配合維護引用計數,適用於 alloc、copy、new、mutablecopy 之類的函式。

###二、 autorelease在實現上的優化

#####1. 優化的場景

假設我們有個方法,返回乙個物件,方法內部我們 retain 了這個物件,返回的時候我們 autorelease 了這個物件。呼叫方拿到我們的返回值物件,立即進行了 retain,使用完之後進行 release。

#####2. 優化的思路

在上述場景下,省略autorelease和呼叫方的retain不會產生任何問題,這裡的情況是兩次連續的retain和release被優化為一次retain和release,因為:

返回值物件物件安全的穿透了作用域邊界(因為沒有進行 release)。

返回值物件引用計數是平衡的。

#####3. 優化的實現

編譯器進行**分析,判斷函式返回值是否被立即 retain,並設定標誌。函式返回前的 autorelease 以及 retain 乙個函式返回值被替換為objc_autoreleasereturnvalueobjc_retainautoreleasedreturnvalue兩個函式呼叫,在這兩個函式中根據之前設定的標誌來決定是什麼都不做,還是真的 autorelease 和 retain 。(果然,軟體工程當中,沒有什麼問題是增加中間層解決不了的,這裡的 autorelease 、retain 都會替代為中間層 objc_autoreleasereturnvalue、objc_retainautoreleasedreturnvalue,這兩個方法會根據標誌執行動態化邏輯)

###三、 為什麼alloc、copy、new、mutablecopy之類的方法返回值不autorelease,而是把release的責任交給呼叫方?

為了執行效率、記憶體使用效率。把物件加入 autorelease pool 是有效能開銷的,如果 alloc 方法的返回值也 autorelease 的話,在沒有編譯器和執行時的優化的情況下,所有的物件都要等到 autorelease pool 幹的時候才有可能被**。而函式返回前不 release,將 release 的責任轉移給呼叫方,呼叫方可以在使用完返回值之後及時的 release 返回值,從而提公升記憶體使用效率。

###四、為什麼不所有方法都像 alloc、copy、new、mutablecopy 之類的方法一樣,把 release 的責任交給呼叫方,而使用 autorelease ?

有兩種情況,

問題在於,函式對呼叫方來說是黑盒,所以呼叫方無法確定返是否需要release一次函式返回值。而 alloc、copy、new、mutablecopy內部一定有一次retain,(如果你在這些函式中返回乙個你沒有 retain 的物件,系統會自動加上 retain 語句), 所以確定需要進行一次 release ,因而可以把 release 的責任交給呼叫方。

總的來說,要把release責任交給呼叫方,函式要具有確定性。

###五、並不是所有的函式返回值都需要autorelease

autorelease 是特殊的 release,作用也是讓引用計數減一。如果函式體內沒有 retain,就不需要 autorelease。舉個例子,類property的get方法返回值是不需要 autorelease的,直接返回即可。

- (someclass *)someinstance

當然,需要不需要是一回事,可以不可以是另外一回事,你可以去做不需要的事,比如把 get 方法實現成下面這樣。

- (someclass *)someinstance

這樣的結果是物件的屬性的生命週期可能長於物件本身。我覺得不符合「屬性歸屬於物件,生命週期依賴於物件的認知」。不支援這麼實現get方法。

最後內部實現上用雙向鍊錶,page,哨兵等等。沒有深究。

autorelease 的基本使用

5 autorelease 的基本使用 0,引入 person p persom new p release p run p run 希望不立即釋放,待 run執行完後再釋放 1,自動釋放池簡介及 autorelease 簡介自動釋放池1 在 ios 執行過程中 會建立無數個池子 這些池子都是以棧的...

autorelease基本使用

autorelease是一種支援引用計數的記憶體管理方式,只要給物件傳送一條autorelease訊息,會將物件放到乙個自動釋放池中,當自動釋放池被銷毀時,會對池子裡面的所有物件做一次release操作 注意,這裡只是傳送release訊息,如果當時的引用計數 reference counted 依...

hadoop的使用場合與不使用場合

1.在web中頁面的快速響應中不適合用hadoop 響應時間在ms級別 2.大量的小檔案處理不使用用hadoop 元資料較多,而且元資料是儲存在namenode中的,記憶體占用大 3.hdfs中的block 乙個block只是可以儲存乙個檔案 但是乙個檔案可以由多個塊組成,預設情況下乙個block有...