思考: 如果我的Student有三个成员变量 那么会占用对少个字节? (class_getInstanceSize([Student class]) 的输出是多少? malloc_size((__bridge const void *)stu的输出是多少? )
#import <malloc/malloc.h>
#import <OBJC/runtime.h>
///> Student类
@interface Student: NSObject{
@public
int _no;
int _age;
int _gender;
}
///> 实际底层的结构体 结构
//struct Student_IMPL{
// Class isa,
// int _no,
// int _age;
// int _gender;
//}
@end
@implementation Student
@end
///> main
int main(int argc, char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc]init];
stu->_no = 4;
stu->_age = 5;
stu->_gender = 1;
NSLog(@"%zd", class_getInstanceSize([Student class]));
NSLog(@"%zd", malloc_size((__bridge const void *)stu));
/**输出结果
24
32
*/
}
return 0;
}
复制代码
- 最终的输出结果为:
- class_getInstanceSize: 24
- malloc_size: 32
首先探究下一为什么malloc_size的输出为32 ?
可以使用Xcode自带的 工具 去查看 系统分配的内存和使用的内存情况。
首先我们需要拿到stu对象的内存地址:
xcode控制台常用指令:(地址) 这里我们的内存地址为:<Student: 0x600002746b60>
然后选择:Debug --> Degug Workflow --> View Memory
在下方的位置输入我们刚刚得到的内存地址后就可以了,stu的内存结构如上图所示
直到红线的位置都是stu所开辟的存储空间,直到红色数线后才有了新的值, 在之前都是00值而且在内存中内存是连续的, 所以我们可以认为,直到红色竖线位置之前都是stu所分配的存储空间
如上图所示
- 绿色区域:前8位就是我们上节课所说的对象的本质实质上就是结构体:然而结构体中的带有Class isa 指针,每个对象中都会包含这个Class isa 这个指针。这个指针占用了8个字节。
- 蓝色区域:成员变量_no:因为是Int类型所以真用了4个字节。
- 黄色区域:成员变量_age:因为是Int类型所以真用了4个字节。
- 灰色区域:成员变量_gender:因为是Int类型所以真用了4个字节。
- 白色区域:所有的都是00,可以认为是已经开辟的的内存但是并没有使用的区域。
由上图分析:我们可以得出 stu实际上在内存中分配了32个字节的内存空间 也就是 malloc_size() 所输出的开辟内存空间的字节数。
接下来探究下一为什么class_getInstanceSize的输出为24 ?
class_getInstanceSize 顾名思义 获取类的实例大小 isa占用8个 + _no:4个 + _age4个 + _gender4个
@interface Student: NSObject{
@public
Class isa; ///> 8
int _no; ///> 4
int _age; ///> 4
int _gender; ///> 4
} /// 计算相加后 为20个,
复制代码
结构体存在一个内存对其的操作,这样有利于CPU的访问, 在CO中用到的内存对其的一条规则就是: 结构体为了保证内存对其 最重的真用内存一定是占用最大的一个变量的倍数, 在这里我们isa占用了8个字节数, 所以虽然实际上只使用了20个字节,但是为了保证内存对其的规则 所以使用了24个字节,
如果我们有4个成员变量的话:
@interface Student: NSObject{
@public
Class isa; ///> 8
int _no; ///> 4
int _age; ///> 4
int _gender; ///> 4
int _height; ///> 4
} /// 计算相加后 为24个,
复制代码
我们真用的内存还是24,开辟依旧是32个字节。
如果在增加一个成员变量的话:
@interface Student: NSObject{
@public
Class isa; ///> 8
int _no; ///> 4
int _age; ///> 4
int _gender; ///> 4
int _height; ///> 4
int _weight; ///> 4
} /// 计算相加后 为28个,
复制代码
为了保证内存对其所以大小为32个字节,开辟依旧是32个字节。
malloc_size() 也运用了内存对其的 上篇文章中解释了为什么给类的内存分配了16个字节, 由于内存对其的原因所以stu类分配了32个字节。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 真实案例引发的 iOS 底层实现窥探
- 窥探iOS底层实现-- KVO/KVC的本质
- iOS源码解析:runtime isa,class底层结构窥探
- 窥探iOS底层实现--instance、class、meta-calss对象的isa和superclass
- 窥探SDWebImage
- 窥探现代浏览器架构-三
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入理解 Flask
[美]Jack Stouffer / 苏丹 / 电子工业出版社 / 2016-7-1 / 79.00
Flask 是一种具有平缓学习曲线和庞大社区支持的微框架,利用它可以构建大规模的web应用。学习上手Flask非常轻松,但要深入理解却并不容易。 本书从一个简单的Flask应用开始,通过解决若干实战中的问题,对一系列进阶的话题进行了探讨。书中使用MVC(模型-视图-控制器)架构对示例应用进行了转化重构,以演示如何正确地组织应用代码结构。有了可扩展性强的应用结构之后,接下来的章节使用Flask......一起来看看 《深入理解 Flask》 这本书的介绍吧!