在64的系统中定义一个NSObject所占的内存是多少呢?
答案是:16个字节
为什么的是16个字节呢?
因为NSObject的底层实现如下:
// NSObject Implementation
struct NSObject_IMPL {
Class isa; // 8个字节
};
引入
#import <objc/runtime.h>
#import <malloc/malloc.h>
打印相关的信息:
NSObject *obj = [[NSObject alloc] init];
// 16个字节
// 获得NSObject实例对象的成员变量所占用的大小 >> 8
NSLog(@"%zd", class_getInstanceSize([NSObject class]));
// 获得obj指针所指向内存的大小 >> 16
NSLog(@"%zd", malloc_size((__bridge const void *)obj));
发现实际上创建NSObject所需的内存空间是8个字节,但是系统实际开辟的内存空间是16个字节,问题出在了哪里?
查看源码我们发现一句这样的代码:
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;
}
当size小于16时,系统会强制转成16个字节,所以系统开辟实际空间为16个字节。
随之而来的一个问题是当我们自己的创建一个类时,实际开辟的内存空间是多少呢?
我们明白,类的本质的结构体,结构体有一个原则叫做内存对齐。
内存对齐主要遵循下面三个原则:
1.结构体变量的起始地址能够被其最宽的成员大小整除。
2.结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节。
3.结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节。
注:
其实这里有点不严谨,编译器在编译的时候是可以指定对齐大小的,实际使用的有效对齐其实是取指定大小和自身大小的最小值。
参考:如何理解 struct 的内存对齐?
所以真实的大小要看其最大的成员变量的长度,然后进行计算。
举个简单的例子:
#import <Foundation/Foundation.h>
//#import <objc/runtime.h>
#import <objc/message.h>
#import <malloc/malloc.h>
@interface Student : NSObject{
@public
int _age;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
// NSLog(@"Hello, World!");
Student *stu = [[Student alloc] init];
NSLog(@"%zd ",class_getInstanceSize([Student class]));//16
NSLog(@"%zd ",malloc_size((__bridge const void *)stu));//16
}
return 0;
}
#import <Foundation/Foundation.h>
//#import <objc/runtime.h>
#import <objc/message.h>
#import <malloc/malloc.h>
@interface Student : NSObject{
@public
int _age;
int _no;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
// NSLog(@"Hello, World!");
Student *stu = [[Student alloc] init];
NSLog(@"%zd ",class_getInstanceSize([Student class]));//16
NSLog(@"%zd ",malloc_size((__bridge const void *)stu));//16
}
return 0;
}
看两段代码的区别,下面一段代码多了一个 int _no; 但是开辟出来的空间和上面的一样。
模拟一下内存显示:
内存
所以对象开辟的实际内存空间是16个字节
iOS 又有自己分配内存的对齐方式,最大是256个字节,最小是16个字节,(16 32 48 64 80 96 112...为16的倍数),超过256就会采用别的分配内存的方式(暂时不讨论),所以当我们创建的类开辟内存空间的时候,系统会拿大于等于实际内存的整块的大小给你,而不是实际大小。
网友评论