参考链接:
我们知道OC实例对象的指针占用的内存为8字节(isa指针,或者说是objc_class结构体指针)。
但是,实际上一个OC对象的内存占用为至少16字节。
在OC对象alloc方法的源码中,可以看到:
static __attribute__((always_inline))
id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
if (!cls) return nil;
assert(cls->isRealized());
// Read class's info bits all at once for performance
bool hasCxxCtor = cls->hasCxxCtor();
bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
size_t size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
if (!zone && fast) {
obj = (id)calloc(1, size);
if (!obj) return nil;
obj->initInstanceIsa(cls, hasCxxDtor);
}
else {
if (zone) {
obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (!obj) return nil;
// Use raw pointer isa on the assumption that they might be
// doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (cxxConstruct && hasCxxCtor) {
obj = _objc_constructOrFree(obj, cls);
}
return obj;
}
其中,instanceSize函数的实现为:
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16bytes.
if (size < 16) size = 16;
return size;
}
可以看出,在分配内存时,OC对象的最小内存占用为16字节。
而通过查看内存分配可知,OC对象的内存是按照16字节进行对齐的。
因此,在当类中存在其他属性时,在内存分配时,不足的需要按16字节进行补齐。
例如:
@interface TestClass : NSObject
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, assign) int height;
@property (nonatomic, assign) int row;
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
TestClass *obj = [TestClass new];
obj.age = 4;
obj.height = 5;
obj.row = 6;
NSLog(@"类的实例尺寸----%zd", class_getInstanceSize(obj.class));
const void *objPtr = (__bridge const void *)obj;
NSLog(@"类实例分配的空间====%zd", malloc_size(objPtr));
}
return 0;
}
输出为:
2019-09-12 11:23:08.682507+0800 AlgorithmLearning[30513:6166466] 类的实例尺寸----24
2019-09-12 11:23:08.682960+0800 AlgorithmLearning[30513:6166466] 类实例分配的空间====32
通过查看obj的内存分配可以看到(lldb的”x 地址“指令):
(lldb) x 0x000000010102be80
0x10102be80: 09 25 00 00 01 80 1d 00 05 00 00 00 06 00 00 00 .%..............
0x10102be90: 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
可以看出,前8字节为objc_class指针,后面依次为4字节的height,4字节的row,之后是8字节的age。
在前16字节中,因为占用内存已满,因此,要开辟第二行来存储age,所以,实例的尺寸为 8 + 4 + 4 + 8 = 24 字节。但由于内存分配按照16字节对齐,因此第二行还要补齐缺失的8字节,因此obj实例实际分配的内存空间为 24 + 8 = 32字节。