也談引用計數

2021-08-26 13:01:51 字數 1090 閱讀 7997

引用計數作為一種重要的gc(garbage collection)演算法早已有之,不過也許在ios流行後,作為objc的重要元素,它才廣為人知。

當年學objc時,碰到的最大難點也就是引用計數。manager把objc入門教材給我時,囑我須細看記憶體管理一章,深然其說。從一片茫然到知其用法,直到向安居客一位大牛請教了幾次後,才發現人家是理解引用計數的思想的,而我之前只是知道它的用法。

在上海時,我們幾個合租一套房的朋友就熱水器的使用問題協商,協商的結果是——洗完澡後,如果夜已深,就把熱水器關掉。當時我天天寫objc**,於是想出的餿主意是——如果準備洗澡,就把自己的卡片貼在熱水器旁,洗完了就把卡片取下——卡片的retaincount為0時,把熱水器關掉。

在這個例子中,熱水器是一塊記憶體空間,而我們每個人是乙個指標;某人準備洗澡時,即該指標指向熱水器;貼上卡片,即引用計數+1。當卡片數為0時,關掉熱水器,即釋放記憶體空間。

這個例子並不算好,因為一塊已申請的記憶體空間是可以「同時」被多個指標使用的,不存在先後次序關係(洗澡則需要排隊)。

考慮乙個自習教室,只有一盞燈,為自習教室中的所有同學所共享。同學們學習很認真,認真得並不知道,不關心這間教室還有多少同學——他們都覺得這盞燈是被自己使用的。但事實上這盞燈的明暗變化影響著所有的同學。

也許這個例子更切合實際一些。nsobject作為所有objc類的基類,有乙個方法,retaincount,用來讀取該指標所指向的記憶體空間的引用計數。在實際程式設計中,不應該把retaincount作為邏輯判斷的條件——因為每位同學並不關心這間教室還有多少同學,燈依然被正常使用。這也是我初學objc時犯過的錯誤,後被大牛糾正。retaincount是用來debug的。

即便ms正確地使用引用計數,該retain的地方retain,該release的地方release,還是有可能發生記憶體洩漏——迴圈引用。

考慮自習教室的例子,夜深人靜,教室裡只剩一位同學,而這位同學也該回寢室了——但他發現乙個嚴重的問題,這盞燈怎麼關也關不上,作為乙個節約用電,有責任感的社會主義好青年,他在教室裡守了一夜——關不上燈,他也不走。

其實,這盞燈是杭電自動化學院的最新研究成果——運用了模式識別,聲控,紅外線探測,腳臭識別等技術,當探測到教室裡沒人時,會自動關上。

——這便是迴圈引用導致的記憶體洩露問題。

自動引用計數

每當你產生乙個物件,arc分配一大塊控制項去儲存這個物件。除此之外,當乙個物件是不在需要,arc 將會收回這個例項物件所佔的空間。如果乙個物件的空間被釋放掉,但是你任然通過物件的引用呼叫方法或者屬性,你的程式將要崩潰。為了不讓物件被釋放掉 arc將會追蹤有多少屬性 常量 變數正在引用這個物件。只要有...

引用計數 copy on write

拷貝通常分為值拷貝也叫淺拷貝和深拷貝,當拷貝方式為淺拷貝時就會有以下兩個問題 1 當需要調析構函式時,會出現同一塊空間被析構兩次的情況 2 如果是對指標的淺拷貝,會讓兩個指標同時管理同一塊空間,當乙個指針對這塊空間進行修改時,會影響到另外乙個指標。通過引用計數加寫時拷貝可以有效地解決這些問題。引用計...

自動引用計數

使用弱引用解決迴圈強引用 如果兩個變數屬性都可以設定為nil,那麼就用弱引用來設定其中乙個屬性來解決迴圈強引用。class person weak var apartment apartment?deinit class apartment deinit var aperson person?per...