OC instance 对象本质二

2018-08-11  本文已影响8人  曹来东
image.png
执行如下指令,生成.cpp文件
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

检索Student_IMPL {查看Student结构体实现如下:

struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _no;
    int _age;
};

struct NSObject_IMPL NSObject_IVARSNSObject的底层实现,即NSObject_IMPL:

struct NSObject_IMPL {
    Class isa
};

所以继承自NSObjectStudent的实现相当于:

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

如上所示,一个子类会将自父类继承来的成员变量放在成员变量列表的起始位置,先排列父类的成员变量,然后再排列自己的成员变量.

Student对象的内存分配如下:

image.png

obj指针的地址为:Student对象的第一个成员变量的地址:isa的地址.

image.png
image.png
通过上面两幅图可以证明:Student底层本质就是Student_IMPL结构体.

Student对象 结构图:

image.png

思考:

image.png

内存对其:

image.png

代码打印:

image.png

为什么Person对象分配的内存和实际占用的内存都为16?

Person 底层实现:

struct NSObject_IMPL {
    Class isa;
}

struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _no;
}

@interface Person : NSObject
{
    int _no;
}
image.png
Person对象正常应该占用12个字节.因为内存对其原则:
结构体大小 需为 结构体最大成员变量(struct NSObject_IMPL)所占内存的整数倍所以Person的占用的内存大小为 8 * 2 = 16.
从如下函数中也可看出class_getInstanceSize底层调用的是如下函数:
 uint32_t alignedInstanceStart() {
        return word_align(unalignedInstanceStart());
    }

unalignedInstanceStart()该函数为未做内存对其的内存大小//12
word_align(12)该函数对其后的内存大小//16

instance对象中只有 成员变量,没有方法列表.方法列表在Class对象当中.

@interface Person : NSObject
{
    int _no;
}
@property (nonatomic,assign) int height;
@end

Person instance对象的底层实现:

struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _no;
    int _height;
};

可以看到实现中没有heightgettersetter方法.

设计技巧:

上一篇 下一篇

猜你喜欢

热点阅读