標籤:
看到此篇文章,就當作你已經學習好了物件導向的基本。
(我認為這種理論概念的東西,沒有任何一位老師一說就就會懂。
這裡就不提我當年的老師多麼NB,他說了幾次我都沒懂,可能是我笨。
大家還是自己領悟,主要還是多敲代碼,這樣更容易理解為什麼要物件導向)
我們現在要介紹的是oc 關於記憶體的一系列介紹。
之前你也看到在第一片文章中。@autoreleasepool
這個東西是在Xcode4.2及之後的版本中由於引入的ARC(Automatic Reference Counting)機制。
跟java的GC功能相同。
但是是兩碼事,ARC是編譯時間編譯器“幫你”插入了原本需要自己手寫的記憶體管理代碼,
而非像GC一樣運行時的記憶體回收系統。而是程式編譯時間Xcode可以自動給你的代碼添加記憶體釋放代碼。
但是在ObjC中沒有記憶體回收機制,那麼ObjC中記憶體又是如何管理的呢?
其實在ObjC中記憶體的管理是依賴對象引用計數器來進行的:
在ObjC中每個對象內部都有一個與之對應的整數(retainCount),
叫“引用計數器”,當一個對象在建立之後它的引用計數器為1,
當調用這個對象的alloc、retain、new、copy方法之後引用計數器自動在原來的基礎上加1
(ObjC中調用一個對象的方法就是給這個對象發送一個訊息),
當調用這個對象的release方法之後它的引用計數器減1,
如果一個對象的引用計數器為0,則系統會自動調用這個對象的dealloc方法來銷毀這個對象。
所以 只要alloc init後 不用的對象一定要release 否則就會造成記憶體泄露。
而java的記憶體則適用一種比較複雜的記憶體釋放機制。
簡單介紹下java的記憶體,java任何一款虛擬機器都沒有同上面類似的清理方法。
java虛擬機器的思路是一切獲得對象都能追溯到期存活的堆棧或靜態儲存區,
遍曆所有的引用就能找到所有活得對象。對發現的每一個引用必須追蹤到它所引用的對象,
然後是此對象包含的所有引用,如此反覆。直到根源堆棧和靜態區形成的網路全部被訪問到。
在這種方法下,有一種自適應的記憶體回收技術。如何找到存活對象取決於不同的虛擬機器。
有一種發方法叫做停止-複製。它意味著先暫停程式(它不屬於後台垃圾清理)然後將
他們全部拷貝到一塊 新分離的堆記憶體中。之後刪除原來的堆記憶體全部對象。
這樣開始肯能效率比較慢(兩個原因.1是要有兩個堆 2是兩個堆來回折騰),當程式慢慢穩定後。
會轉換成 標記-清理
“標記-清掃”所依據的思路同樣是從堆棧和靜態儲存區出發,遍曆所有的引用,進而找出所有存活的對象。
每當它找到一個存活對象,就會給對象設一個標記,這個過程中不會回收任何對象。
只有全部標記工作完成的時候,清理動作才會開始。
在清理過程中,沒有標記的對象將被釋放,不會發生任何複製動作。
所以剩下的堆空間是不連續的,記憶體回收行程要是希望得到連續空間的話,就得重新整理剩下的對象。
想想java的記憶體管理機制就夠高端、省心。
這裡我們既然瞭解了oc 和java 的記憶體回收機制,就不得不探討下這個對象初始化分配記憶體的內容了。
初始化關鍵詞:new 和 alloc init
在實際開發中很少會用到new,一般建立對象咱們看到的全是[[className alloc] init]
這是為什麼呢?
不知大家發現了沒有:如果使用new的話,初始化方法被固定死只能調用init.不能調用我們準備好的別的初始化方法
這樣是十分不靈活的。
但是除了這種預設初始化外還有別的不同麼。答案是當然有
藉助源碼我們詳細看看他們的區別
+ new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
//而 alloc/init 像這樣:
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{
return self;
}
區別只在於alloc分配記憶體的時候使用了zone.
這個zone是個什麼東東呢?
它是給對象分配記憶體的時候,
把關聯的對象分配到一個相鄰的記憶體地區內,
以便於調用時消耗很少的代價,提升了程式處理速度;
objective-c快速入門教程(三)