Objective-C实例对象的内存布局

结论:

实例对象的内存布局情况如下:
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
  1. 可以看到NSObject,Parent和Child的实例变量大小分别是8,16和24。所以,子类的实例对象确实包含了父类的实例变量。
  2. 通过object_getClass([NSObject class])获取到了NSObject的meta class对象,再通过class_getInstanceSize(object_getClass([NSObject class]))获取到的是NSObject的class object的大小,可以看到Parent,Child和NSObject的class object的确一样大,都是40。
  3. 通过class_getInstanceSize([[NSObject class] class])获取到的不是class object的大小,还是NSObject的instance object的大小。

你可能感兴趣的:(Objective-C实例对象的内存布局)