struct 結(jié)構(gòu)體名{
? ? ? ? 類型名 成員名1;
? ? ? ? 類型名 成員名2;
? ? ? ? ... ...
? ? ? ? 類型名 成員名n;
};
struct {
intage?
;inttag ;
} structTwo;
typedef可以對(duì)數(shù)據(jù)類型進(jìn)行重命名鉴竭,因此在定義結(jié)構(gòu)體的時(shí)候可以使用它來簡(jiǎn)化操作捣卤。
/**
*? 定義結(jié)構(gòu)體
*/typedef struct {
? ? char*name;//姓名
unsignedintage;//年齡
} Student;
int main(intargc,constchar* argv[]) {
? ? //聲明結(jié)構(gòu)變量Student student1 = {"jredu",21};
? ? return0;
}
//struct programmer proTest = {"Garvey",28,"13823992034"};
ios-結(jié)構(gòu)體和類的區(qū)別:
1、結(jié)構(gòu)體只能封裝屬性歧焦,類卻不僅可以封裝屬性也可以封裝方法涛菠。如果一個(gè)封裝的數(shù)據(jù)有屬性也有行為残黑,就只能用類了寝优。
2苫亦、結(jié)構(gòu)體變量分配在棧毛肋,而OC對(duì)象分配在堆,棧的空間相對(duì)于堆來說是比較小的屋剑,但是存儲(chǔ)在棧中的數(shù)據(jù)訪問效率相對(duì)于堆而言是比較高
3润匙、堆的存儲(chǔ)空間比較大,存儲(chǔ)在堆中的數(shù)據(jù)訪問效率相對(duì)于棧而言是比較低的
4唉匾、如果定義一個(gè)結(jié)構(gòu)體孕讳,這個(gè)結(jié)構(gòu)體中有很多屬性,那么這個(gè)時(shí)候結(jié)構(gòu)體變量在棧中會(huì)占據(jù)很多空間巍膘,這樣的話就會(huì)降低效率
5厂财、我們使用結(jié)構(gòu)體的時(shí)候最好是屬性比較少的結(jié)構(gòu)體對(duì)象如果屬性較多的話就要使用類了
6、結(jié)構(gòu)體賦值的話是直接賦值峡懈,對(duì)象的指針璃饱,賦值的是對(duì)象的地址。
思考: 一個(gè)OC對(duì)象在內(nèi)存中是如何布局的肪康。 NSObjcet的底層實(shí)現(xiàn)荚恶,點(diǎn)擊NSObjcet進(jìn)入發(fā)現(xiàn)NSObject的內(nèi)部實(shí)現(xiàn)
@interface NSObject {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wobjc-interface-ivars
"Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop}
@end
轉(zhuǎn)化為c語言其實(shí)就是一個(gè)結(jié)構(gòu)體
struct NSObject_IMPL {
? ? Class isa;
};
那么這個(gè)結(jié)構(gòu)體占多大的內(nèi)存空間呢,我們發(fā)現(xiàn)這個(gè)結(jié)構(gòu)體只有一個(gè)成員磷支,isa指針谒撼,而指針在64位架構(gòu)中占8個(gè)字節(jié)。也就是說一個(gè)NSObjec對(duì)象所占用的內(nèi)存是8個(gè)字節(jié)雾狈。到這里我們已經(jīng)可以基本解答第一個(gè)問題廓潜。但是我們發(fā)現(xiàn)NSObject對(duì)象中還有很多方法,那這些方法不占用內(nèi)存空間嗎箍邮?其實(shí)類的方法等也占用內(nèi)存空間茉帅,但是這些方法所占用的存儲(chǔ)空間并不在NSObject對(duì)象中。
為了探尋OC對(duì)象在內(nèi)存中如何體現(xiàn)锭弊,我們來看下面一段代碼
NSObject *objc = [[NSObject alloc] init];
上面一段代碼在內(nèi)存中如何體現(xiàn)的呢堪澎?上述一段代碼中系統(tǒng)為NSObject對(duì)象分配8個(gè)字節(jié)的內(nèi)存空間,用來存放一個(gè)成員isa指針味滞。那么isa指針這個(gè)變量的地址就是結(jié)構(gòu)體的地址樱蛤,也就是NSObjcet對(duì)象的地址钮呀。
假設(shè)isa的地址為0x100400110,那么上述代碼分配存儲(chǔ)空間給NSObject對(duì)象昨凡,然后將存儲(chǔ)空間的地址賦值給objc指針爽醋。objc存儲(chǔ)的就是isa的地址。objc指向內(nèi)存中NSObject對(duì)象地址便脊,即指向內(nèi)存中的結(jié)構(gòu)體蚂四,也就是isa的位置。
因此此結(jié)構(gòu)體占用多少存儲(chǔ)空間哪痰,對(duì)象就占用多少存儲(chǔ)空間遂赠。因此結(jié)構(gòu)體占用的存儲(chǔ)空間為,isa指針8個(gè)字節(jié)空間+int類型_no4個(gè)字節(jié)空間+int類型_age4個(gè)字節(jié)空間共16個(gè)字節(jié)空間
Student *stu = [[Student alloc] init];
stu -> _no = 4;
stu -> _age = 5;
那么上述代碼實(shí)際上在內(nèi)存中的體現(xiàn)為晌杰,創(chuàng)建Student對(duì)象首先會(huì)分配16個(gè)字節(jié)跷睦,存儲(chǔ)3個(gè)東西,isa指針8個(gè)字節(jié)肋演,4個(gè)字節(jié)的_no ,4個(gè)字節(jié)的_age
那么一個(gè)NSObject對(duì)象占用多少內(nèi)存抑诸??NSObjcet實(shí)際上是只有一個(gè)名為isa的指針的結(jié)構(gòu)體,因此占用一個(gè)指針變量所占用的內(nèi)存空間大小爹殊,如果64bit占用8個(gè)字節(jié)蜕乡,如果32bit占用4個(gè)字節(jié)。
我們發(fā)現(xiàn)只要是繼承自NSObject的對(duì)象边灭,那么底層結(jié)構(gòu)體內(nèi)一定有一個(gè)isa指針异希。
面試題:OC的類信息存放在哪里。 面試題:對(duì)象的isa指針指向哪里绒瘦。
OC的類信息存放在哪里?OC對(duì)象主要可以分為三種
instance對(duì)象(實(shí)例對(duì)象)
class對(duì)象(類對(duì)象)
meta-class對(duì)象(元類對(duì)象)
instance對(duì)象就是通過類alloc出來的對(duì)象称簿,每次調(diào)用alloc都會(huì)產(chǎn)生新的instance對(duì)象
NSObjcet *object1 = [[NSObjcet alloc] init];
NSObjcet *object2 = [[NSObjcet alloc] init];
object1和object2都是NSObject的instace對(duì)象(實(shí)例對(duì)象),但他們是不同的兩個(gè)對(duì)象惰帽,并且分別占據(jù)著兩塊不同的內(nèi)存憨降。 instance對(duì)象在內(nèi)存中存儲(chǔ)的信息包括
isa指針
其他成員變量
衍生問題:在上圖實(shí)例對(duì)象中根本沒有看到方法,那么實(shí)例對(duì)象的方法的代碼放在什么地方呢该酗?那么類的方法的信息授药,協(xié)議的信息,屬性的信息都存放在什么地方呢呜魄?
每一個(gè)類在內(nèi)存中有且只有一個(gè)class對(duì)象悔叽。可以通過打印內(nèi)存地址證明
class對(duì)象在內(nèi)存中存儲(chǔ)的信息主要包括
isa指針
superclass指針
類的屬性信息(@property)爵嗅,類的成員變量信息(ivar)
類的對(duì)象方法信息(instance method)娇澎,類的協(xié)議信息(protocol)
成員變量的值時(shí)存儲(chǔ)在實(shí)例對(duì)象中的,因?yàn)橹挥挟?dāng)我們創(chuàng)建實(shí)例對(duì)象的時(shí)候才為成員變賦值睹晒。但是成員變量叫什么名字趟庄,是什么類型括细,只需要有一份就可以了。所以存儲(chǔ)在class對(duì)象中戚啥。
類方法放在那里奋单??元類對(duì)象 meta-class
每個(gè)類在內(nèi)存中有且只有一個(gè)meta-class對(duì)象。?meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的猫十,但是用途不一樣览濒,在內(nèi)存中存儲(chǔ)的信息主要包括
isa指針
superclass指針
類的類方法的信息(class method)
meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的,所以meta-class中也有類的屬性信息炫彩,類的對(duì)象方法信息等成員變量匾七,但是其中的值可能是空的絮短。
對(duì)象的isa指針指向哪里
當(dāng)對(duì)象調(diào)用實(shí)例方法的時(shí)候江兢,我們上面講到,實(shí)例方法信息是存儲(chǔ)在class類對(duì)象中的丁频,那么要想找到實(shí)例方法杉允,就必須找到class類對(duì)象,那么此時(shí)isa的作用就來了席里。
[stu studentMethod];
instance的isa指向class叔磷,當(dāng)調(diào)用對(duì)象方法時(shí),通過instance的isa找到class奖磁,最后找到對(duì)象方法的實(shí)現(xiàn)進(jìn)行調(diào)用改基。
當(dāng)類對(duì)象調(diào)用類方法的時(shí)候,同上咖为,類方法是存儲(chǔ)在meta-class元類對(duì)象中的秕狰。那么要找到類方法,就需要找到meta-class元類對(duì)象躁染,而class類對(duì)象的isa指針就指向元類對(duì)象
[Student studentClassMethod];復(fù)制代碼
class的isa指向meta-class 當(dāng)調(diào)用類方法時(shí)鸣哀,通過class的isa找到meta-class,最后找到類方法的實(shí)現(xiàn)進(jìn)行調(diào)用
當(dāng)對(duì)象調(diào)用其父類對(duì)象方法的時(shí)候吞彤,又是怎么找到父類對(duì)象方法的呢我衬?,此時(shí)就需要使用到class類對(duì)象superclass指針饰恕。
[stu personMethod];
[stu init];
當(dāng)Student的instance對(duì)象要調(diào)用Person的對(duì)象方法時(shí)挠羔,會(huì)先通過isa找到Student的class,然后通過superclass找到Person的class埋嵌,最后找到對(duì)象方法的實(shí)現(xiàn)進(jìn)行調(diào)用破加,同樣如果Person發(fā)現(xiàn)自己沒有響應(yīng)的對(duì)象方法,又會(huì)通過Person的superclass指針找到NSObject的class對(duì)象莉恼,去尋找響應(yīng)的方法
當(dāng)類對(duì)象調(diào)用父類的類方法時(shí)拌喉,就需要先通過isa指針找到meta-class速那,然后通過superclass去尋找響應(yīng)的方法
[Student personClassMethod];[Student load];復(fù)制代碼
當(dāng)Student的class要調(diào)用Person的類方法時(shí),會(huì)先通過isa找到Student的meta-class尿背,然后通過superclass找到Person的meta-class端仰,最后找到類方法的實(shí)現(xiàn)進(jìn)行調(diào)用
https://juejin.im/post/5ac81c75518825556534c0af
對(duì)isa、superclass總結(jié)
instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基類的meta-class田藐,基類的isa指向自己
class的superclass指向父類的class荔烧,如果沒有父類,superclass指針為nil
meta-class的superclass指向父類的meta-class汽久,基類的meta-class的superclass指向基類的class
instance調(diào)用對(duì)象方法的軌跡鹤竭,isa找到class,方法不存在景醇,就通過superclass找父類
class調(diào)用類方法的軌跡臀稚,isa找meta-class,方法不存在三痰,就通過superclass找父類
本文面試題總結(jié):
一個(gè)NSObject對(duì)象占用多少內(nèi)存吧寺?
答:一個(gè)指針變量所占用的大小(64bit占8個(gè)字節(jié)散劫,32bit占4個(gè)字節(jié))
對(duì)象的isa指針指向哪里稚机?
答:instance對(duì)象的isa指針指向class對(duì)象,class對(duì)象的isa指針指向meta-class對(duì)象获搏,meta-class對(duì)象的isa指針指向基類的meta-class對(duì)象赖条,基類自己的isa指針也指向自己。
OC的類信息存放在哪里常熙?
答:成員變量的具體值存放在instance對(duì)象纬乍。對(duì)象方法,協(xié)議症概,屬性蕾额,成員變量信息存放在class對(duì)象。類方法信息存放在meta-class對(duì)象彼城。