iOS面试题-一个NSObject对象占用多少个字节?

2021-03-21  本文已影响0人  小荣袁

一个NSObject对象占用多少个字节?

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

// NSObject Implementation
struct NSObject_IMPL {
    Class isa; // 8个字节
};
// 指针
// typedef struct objc_class *Class;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        // 16个字节
        
        // 获得NSObject实例对象的成员变量所占用的大小 >> 8
        NSLog(@"%zd", class_getInstanceSize([NSObject class]));
        
        // 获得obj指针所指向内存的大小 >> 16
        NSLog(@"%zd", malloc_size((__bridge const void *)obj));
        
        // 什么平台的代码
        // 不同平台支持的代码肯定是不一样
        // Windows、mac、iOS
        // 模拟器(i386)、32bit(armv7)、64bit(arm64)
        // 可以通过 命令行工具,生成C++文件
        // xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
        // 然后把编译成功的cpp文件,拖入到工程中,注意 Copy items if needed 不勾选
        // 然后Build Phases中删除main-arm64.cpp编译选项(选中文件点减号或按delete键)
        // 这样文件不参与编译就不会报错了
    }
    return 0;
}
// NSObject Implementation
struct NSObject_IMPL {
    Class isa; // 8个字节
};

通过objc源码实现一探究竟

inline size_t instanceSize(size_t extraBytes) const {
        if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
            return cache.fastInstanceSize(extraBytes);
        }

        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }

用Xcode打断点看内存结构

image.png image.png image.png image.png image.png

总结

回答

  1. 系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
  2. 但是NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数来获取),其实就是isa

扩展到有继承结构的对象

struct Student_IMPL {
    Class isa;
    int _no;
    int _age;
};


@interface Student : NSObject
{
    @public
    int _no;
    int _age;
}
@end

@implementation Student

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Student *stu = [[Student alloc] init];
        stu->_no = 4;
        stu->_age = 5;
        
        // 16
        NSLog(@"%zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"%zd", malloc_size((__bridge const void *)stu));
        
        struct Student_IMPL *stuImpl = (__bridge struct Student_IMPL *)stu;
        // no is 4, age is 5
        NSLog(@"no is %d, age is %d", stuImpl->_no, stuImpl->_age);
    }
    return 0;
}
image.png

扩展到有多重继承的结构

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

@implementation Person

@end

@interface Student : Person
{
    int _no;
}
@end

@implementation Student

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        // 16
        NSLog(@"person --- %zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"person --- %zd", malloc_size((__bridge const void *)person));
        
        Student *stu = [[Student alloc] init];
        // 16
        NSLog(@"stu --- %zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"stu --- %zd", malloc_size((__bridge const void *)stu));
    }
    return 0;
}
image.png image.png

Objective-C不同数据类型占用字节大小

类型 32位机器 64位机器
BOOL 1 1
bool 1 1
int 4 4
short 2 2
long 4 8
long long 8 8
NSInteger 4 8
float 4 4
double 8 8
CGFloat 4 8
char 1 1
指针地址 4 8
上一篇 下一篇

猜你喜欢

热点阅读