注:本文摘自唐巧博客,方便以后查閱。請諒解
問題
一個 Objective-C 對象的內存結構是怎樣的?
答案
這是一道老題,或許很多人都準備過,其實如果不是被每個公司都考查的話,這道題可以看看候選人對于 iOS 背后底層原理的感興趣程度。真正對編程感興趣的同學,都會對這個多少有一些好奇,進而在網上搜索并學習這方面的資料。
以下是本題的簡單回答:
如果把類的實例看成一個C語言的結構體(struct),它首先包含的是一個 isa 指針,而類的其它成員變量依次排列在結構體中。排列順序如下圖所示:
為了驗證該說法,我們在Xcode中新建一個工程,在main.m中運行如下代碼:
#import
@interfaceFather:NSObject{
int_father;
}
@end@implementationFather
@end
@interfaceChild:Father{
int_child;
}
@end
@implementationChild
@end
intmain(intargc,char* argv[])
{
Child * child = [[Child alloc] init];
@autoreleasepool{
// ...
}
}
我們將斷點下在@autoreleasepool處,然后在Console中輸入p *child,則可以看到Xcode輸出如下內容,這與我們上面的說法一致。
(lldb) p *child
(Child) $0 = {
(Father) Father = {
(NSObject) NSObject = {
(Class) isa = Child
}
(int) _father = 0
}
(int) _child = 0
}
因為對象在內存中的排布可以看成一個結構體,該結構體的大小并不能動態變化。所以無法在運行時動態給對象增加成員變量。
注:需要特別說明一下,通過objc_setAssociatedObject和objc_getAssociatedObject方法可以變相地給對象增加成員變量,但由于實現機制不一樣,所以并不是真正改變了對象的內存結構。
下一期的問題:對象內存結構中的 isa 指針是用來做什么的,有什么用?