iOS 开发 Objective-C iOS精选面试题

iOS 底层 day01 OC对象的本质

2020-08-20  本文已影响0人  望穿秋水小作坊
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

@interface Person : NSObject
{
    @public
    int _age;
}
@end
@implementation Person
@end

@interface Student : Person
{
    @public
    int _no1;
    int _no2;
}
@end
@implementation Student
@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        Student *stu = [[Student alloc] init];
        Person *person = [[Person alloc] init];
    }
    return 0;
}

代码简述:构建了一个 Person 类,带有一个 _age 成员变量;构建了一个 Student 类,继承自 Person 类,带有 _no1_no2 成员变量;

请问objstuperson 这三个实例对象,运行时分别会分配多少内存空间? 如果清楚的知道,那么请关闭自此文章。

1. 什么是 Objective-C ?
2. 既然 Objective-C 是对标准 C 的扩展,请思考,那么 NSObject 底层是用 C 语言的什么来实现的呢?
3. 如何证明是使用 C 语言的结构体来实现的呢?
// IMPL 就是 implement 的缩写
struct NSObject_IMPL {
    Class isa;
};
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
};
struct Student_IMPL {
    struct Person_IMPL Person_IVARS;
    int _no1;
    int _no2;
};
4. 那么从上面结构体来看,一个 NSObject_IMPL 结构体对象,理论上会分配多少内存空间呢?
5. 实际上我们项目运行中,NSObject 会占据多少内存呢?我们借助两个函数分析。
        NSObject *obj = [[NSObject alloc] init];
        NSLog(@"%zu",class_getInstanceSize([NSObject class]));
        NSLog(@"%zu",malloc_size((__bridge const void *)(obj)));

// 输出日志
// 2020-08-20 15:47:58.227486+0800 Demo3[7428:431600] 8
// 2020-08-20 15:47:58.228025+0800 Demo3[7428:431600] 16
6. 分析 class_getInstanceSize 方法, 我们只能下载 objc4 源码进行分析了
size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() {
  return word_align(unalignedInstanceSize());
}
7. 分析 malloc_size 方法
// Replaced by ObjectAlloc
+ (id)allocWithZone:(struct _NSZone *)zone {
    return _objc_rootAllocWithZone(self, (malloc_zone_t *)zone);
}

_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
{
    id obj;
    obj = class_createInstance(cls, 0);
    return obj;
}

class_createInstance(Class cls, size_t extraBytes)
{
    return _class_createInstanceFromZone(cls, extraBytes, nil);
}

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                              bool cxxConstruct = true, 
                              size_t *outAllocatedSize = nil)
{
    id obj;
    size_t size = cls->instanceSize(extraBytes);
    obj = (id)calloc(1, size);
}

size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
 }
8. 那么 person 占据多少字节呢?
        Person *person = [[Person alloc] init];
        NSLog(@"person:class_getInstanceSize: %zu",class_getInstanceSize([Person class]));
        NSLog(@"person:malloc_size: %zu",malloc_size((__bridge const void *)(person)));
        


// 打印结果
2020-08-20 16:16:59.162324+0800 Demo3[7806:473714] person:class_getInstanceSize: 16
2020-08-20 16:16:59.162382+0800 Demo3[7806:473714] person:malloc_size: 16
9. 那么 stu 占据多少字节呢?
        Student *stu = [[Student alloc] init];
        NSLog(@"stu:class_getInstanceSize: %zu",class_getInstanceSize([Student class]));
        NSLog(@"stu:malloc_size: %zu",malloc_size((__bridge const void *)(stu)));
        
// 打印结果
2020-08-20 16:16:59.162441+0800 Demo3[7806:473714] stu:class_getInstanceSize: 24
2020-08-20 16:16:59.162473+0800 Demo3[7806:473714] stu:malloc_size: 32
上一篇下一篇

猜你喜欢

热点阅读