Objective-C中MRC和ARC的自我理解
MRC: 手動引用計數。
?
alloc -- 分配一個對象的內存空間
retain --使一個對象的引用計數加1
release --使一個對象的引用計數減1
retainCount --獲取當前對象的引用計數值
aotorelese --調用對象的aotorelease方法的話,將對象的內存管理放到aotorelease poll中,當aotorelease poll結束的時候自動調用release操作,使引用計數減1
dealloc 在MRC中調用dealloc,需要顯示的調用 super dealloc方法,廢棄父類的方法。
在MRC模式下必須遵循誰創建,誰釋放,誰引用,誰管理
ARC : 自動引用計數
ARC是編譯器(LLVM)在對應的位置自動插入retain和release操作之外,還需要Runtime的功能支持,是LLVM和Runtime協作的結果。ARC中禁止手動調用retain、release、retainCount、dealloc.
ARC中新增了weak、strong屬性關鍵字。
MRC和ARC的區別:
1、MRC是手動管理內存,ARC是自動管理內存,由編譯器和Runtime進行協作。
2、ARC中禁止調用retain、release、autorelease、retainCount、dealloc操作
在MRC下使用ARC,使用?-fobjc-arc修飾文件,啟用ARC
在ARC下使用MRC,使用?-fno-objc-arc修飾文件,禁止ARC
strong和weak
strong強引用,執行了retain操作,weak弱引用,表示該屬性是一種非擁有關系,沒有執行retain操作。
weak屬性在設置新值時既不保留新值也不會釋放舊值,類似于assign;當對象被釋放時,屬性也會被清空。這樣可以有效地防止崩潰(因為OC中給沒有對象地址的指針發送消息,不會崩潰;但是給有內存地址但地址中是空對象的指針,即野指針,發送消息會崩潰)。
對于weak對象會放入一個hash表中,用weak指向的對象內存地址作為key,當此對象的引用計數值為0時會調用dealloc,使用key在hash表中搜索,將找到的所有對象置為nil。
Runtime如何實現weak變量的自動置nil?
引用計數管理
alloc的實現:
經過一些列函數的封裝調用,最終調用了c函數calloc。
此時并沒有設置引用計數值為1,但是我們通過retainCount獲取到的引用計數值為1。這是什么原因呢?
retain的實現:
// 通過當前對象的指針,經過hash函數的運算,可以快速的在sidetables找到它對應的sidetable SideTable& table = SideTables()[this];// 在sidetable中去獲取引用計數map這樣的一個成員變量,然后通過當前對象的指針,在sidetable的引用計數表中去獲取當前對象的引用計數值。 size_t& refcntStorage = table.refcnts[this];// 對引用計數值進行加1操作,size_t 是unsign long 型的,第一位是weakly_referenced第二位是deallocating 所以這里加的值不是實際的1,而是一個宏定義 SIZE_TABLE_RC_ONE,加的一個偏移量 refcntStorage += SIDE_TABLE_RC_ONE;// 這兩次都是hash查找,也就是說在進行retain操作時經歷了兩次hash查找。思考一下:我們在進行retain操作時,系統是如何查找它對應的引用計數的?
解析:通過兩次hash查找,來找到它對應的引用計數值,然后進行加一操作。這里的兩次查找,第一次是找到對應的sidetable表,第二次是從表的引用計數表中獲取當前對象的引用計數值。
release的實現:
SideTable& table = SideTables()[this];//根據當前對象指針訪問table的引用計數表,查到它當前對應的引用計數表。 RefcountMap::iterator it = table.refcnts.find(this);//把查找到的值進行減一操作 it ->second -= SIDE_TABLE_RC_ONE;retainCount實現:
SideTable& table = SideTables()[this];// 聲明一個局部變量,初始值為1 size_t refcnt_result = 1;// 通過當前對象拿到引用計數表中去查找 RefcountMap :: iterator it = table.refcnts.find(this);// 對結果做一個向右偏移的操作,然后再結合局部變量的1進行加的操作 refcnt_result += it ->second >> SIDE_TABLE_RC_SHIFT;這也就解釋了,alloc出來的對象,我們雖然沒有設置引用計數值為1,但是我們通過retainCount去獲取到的引用計數值為1的原因。
dealloc的實現:
從下面流程圖來講述dealloc的實現原理:首先會先調用一個私有函數_objc_rootDealloc(),這個私有函數會調用一個rootDealloc()函數,在這個函數內部判斷當前對象是否可以釋放;直接釋放的一個判斷條件是【1、判斷當前對象是否使用了非指針型isa(NONPOINTER_ISA); 2、當前對象是否有weak指針指向它,weakly_referenced; 3、當前對象是否有關聯對象 has_assoc; 4、當前對象是否涉及了C++相關的代碼 has_cxx_dtor以及當前對象是否使用ARC來管理內存; 5、當前對象的引用計數是否通過sidetable的引用計數表來維護的has_sidetable_rc。】如果上述5個條件有任一個滿足,那就不能直接釋放,需要調用object_dispose()對象清除函數。如果上述5個條件,都不滿足,那就可以直接調用C函數free()直接釋放。
object_dispose()函數的實現
總結
以上是生活随笔為你收集整理的Objective-C中MRC和ARC的自我理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOSAPP配置多环境
- 下一篇: 360浏览器卸载_有恃无恐“弹弹弹”,安