结论:
实例对象的内存布局情况如下:
ISA指针,
根类的实例变量,
倒数第二层父类的实例变量,
…,
父类的实例变量,
类的实例变量
验证
源码验证
从源码上看,实例对象中只定义了一个isa,但是其他变量是否也存储在了实例变量中呢?
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
其中Class是:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
而objc_class继承自objc_object:
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache;
所以objc_class也是一个对象。
alloc方法
alloc方法创建一个class的实例,实例的isa指针指向class,其他实例变量的内存空间被赋值为0。由此我们可以知道alloc方法为实例变量分配了空间。根据文档描述我们知道实例对象确实为实例变量分配了存储空间,这为我们的认识提供了理论依据。
实验验证
先介绍实验用到的2个方法:
- class_getInstanceSize
返回class的实例对象的大小。
- object_getClass
返回一个对象的class对象。如果对象是实例对象,那么object_getClass返回的就是class对象;如果对象是class对象,那么object_getClass返回的就是meta class对象。
注意:object_getClass函数和class方法的区别,[[object class] class]不会返回实例对象object的meta class对象,返回的还是object的class对象。
实验代码和结果
// 定义两个类
@interface Parent : NSObject
@property (nonatomic, strong) NSString *parentName;
@end
@interface Child : Parent
@property (nonatomic, strong) NSString *childName;
@end
// 测试代码:
NSLog(@"Parent instance object size is: %ld", class_getInstanceSize([Parent class]));
NSLog(@"Child instance object size is: %ld", class_getInstanceSize([Child class]));
NSLog(@"NSObject instance object size is: %ld", class_getInstanceSize([NSObject class]));
NSLog(@"Parent class object size is: %ld", class_getInstanceSize(object_getClass([Parent class])));
NSLog(@"Child class object size is: %ld", class_getInstanceSize(object_getClass([Child class])));
NSLog(@"NSObject class object size is: %ld", class_getInstanceSize(object_getClass([NSObject class])));
// [[NSObject class] class]返回的是NSObject的class object,而不是NSObject的meta class object
NSLog(@"Parent instance object size is: %ld", class_getInstanceSize([[Parent class] class]));
NSLog(@"Child instance object size is: %ld", class_getInstanceSize([[Child class] class]));
NSLog(@"NSObject instance object size is: %ld", class_getInstanceSize([[NSObject class] class]));
测试结果为:
Parent instance object size is: 16
Child instance object size is: 24
NSObject instance object size is: 8
Parent class object size is: 40
Child class object size is: 40
NSObject class object size is: 40
Parent instance object size is: 16
Child instance object size is: 24
NSObject instance object size is: 8
- 可以看到NSObject,Parent和Child的实例变量大小分别是8,16和24。所以,子类的实例对象确实包含了父类的实例变量。
- 通过object_getClass([NSObject class])获取到了NSObject的meta class对象,再通过class_getInstanceSize(object_getClass([NSObject class]))获取到的是NSObject的class object的大小,可以看到Parent,Child和NSObject的class object的确一样大,都是40。
- 通过class_getInstanceSize([[NSObject class] class])获取到的不是class object的大小,还是NSObject的instance object的大小。
网友评论