1.我們的都知道內(nèi)存中一般分成這幾塊區(qū)域
A? 靜態(tài)數(shù)據(jù)區(qū):內(nèi)存在程序啟動的時候才被分配,而且可能直到程序開始執(zhí)行的時候才被初始化,如函數(shù)中的靜態(tài)變量就是在程序第一次執(zhí)行到定義該變量的代碼時才被初始化。所分配的內(nèi)存在程序的整個運(yùn)行期間都存在,如全局變量,static變量等。
注意:初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量與靜態(tài)變量在相鄰的另一塊區(qū)域,同時未被初始化的對象存儲區(qū)可以通過void*來訪問和操縱,程序結(jié)束后由系統(tǒng)自行釋放。
B? 代碼區(qū):存放函數(shù)體的二進(jìn)制代碼;
C? 棧區(qū):存放自動變量。在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元由編譯器自動釋放,超出其作用域外的操作沒有定義。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但分配的內(nèi)存容量有限。棧存放函數(shù)的參數(shù)值,局部變量的值等。
D? 堆區(qū)(自由存儲區(qū)):在運(yùn)行的時候調(diào)用程序(如C中的malloc或C++中的new)分配內(nèi)存,可以在任何時候決定分配內(nèi)存及分配的大小,用戶自己負(fù)責(zé)在何時釋放內(nèi)存(如用free或delete)。堆中的所有東西都是匿名的,這樣不能按名字訪問,而只能通過指針訪問。(只有這個區(qū)域,需要我們手動管理的內(nèi)存)。
E? 常量區(qū): 存儲的都是一些字符串常量,有系統(tǒng)自行分配和回收。
2.類創(chuàng)建對象,每個對象在內(nèi)存中都占據(jù)一定的存儲空間(存放在堆區(qū)中),每個對象都有一份屬于自己的單獨(dú)的成員變量(所以所有的成員變量每個對象都會從類對象中復(fù)制一份到自己的存儲空空間中去,但是不復(fù)制類對象的方法),所有的類對象方法在整個內(nèi)存中只有一份,類對象本身在內(nèi)存中也占據(jù)一份存儲空間,類對象的方法存儲于此(因?yàn)榉椒ǖ谋举|(zhì)就是具有功能的一個函數(shù)體,所以應(yīng)該是存在代碼區(qū))。
那么為了解決,所有的對象的都可以訪問到類對象的方法和公共的成員變量:每一個對象都包含一個isa指針(isa是對象中的隱藏指針).這個指針指向當(dāng)前對象所屬的類。[car run];表示給car所指向的對象發(fā)送一條eat消息,調(diào)用對象的run方法,此時對象會順著內(nèi)部的isa指針找到存儲于類中的方法,執(zhí)行。
在OC中存在一個名為id的類型,這個和上面所說這個isa指針有一定的聯(lián)系.C代碼
typedef struct objc_object {Class isa;
} *id;
其中Class類型為指向objc_class結(jié)構(gòu)體的指針類型.
這些對象在內(nèi)存中都是由其地址唯一標(biāo)示,所有的對象都是id類型的.
3、使用一個類創(chuàng)建多個對象
Car *car = [Car new];
Car *car1 = [Car new]
當(dāng)使用一個類創(chuàng)建多個對象的時候,注意:
1)不同的對象在內(nèi)存中分配的是不同的存儲地址,所以各成員屬性的地址也各不相同
car和car1的isa指針都指向了Car類,當(dāng)調(diào)用[car run]方法的時候,就會順著isa指針找到類對象中的run的方法。
4.繼承時候的的對象存儲
當(dāng)我們一個A類繼承另一個B類的時候,由A創(chuàng)建出來的A對象,都會有一個B類的創(chuàng)建的B對象。所以就等于我們A就擁有了B所有的成員的變量和類對象的方法(不考慮關(guān)鍵字@private的使用情況)。