深入解析iOS开发:类成员变量的内存管理策略

更新:11-09 现代故事 我要投稿 纠错 投诉

其实深入解析iOS开发:类成员变量的内存管理策略的问题并不复杂,但是又很多的朋友都不太了解,因此呢,今天小编就来为大家分享深入解析iOS开发:类成员变量的内存管理策略的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

0x02 过程

我们知道,类的成员变量存储在类对象的class_data_bits_t -class_rw_t -class_ro_t -ivars中。因此,当我们想知道类中有哪些成员变量以及它们是如何排序时,只需要打印列表即可。

在类对象的底层结构下面,我创建了Person类,然后打印了它的成员变量列表,如下所示。

@interface Person : NSObject

@property(非原子,分配)int a;

@property(非原子,分配)BOOL b;

@property(非原子,分配)int c;

@property(非原子,分配)BOOL d;

@结尾

ivar 名称:_b 编码:B 偏移量:8

ivar 名称:_d 编码:B 偏移量:9

ivar 名称:_a 编码:i 偏移量:12

ivar name: _c encode: i offset: 16 可以发现,成员变量并不是按照我们定义的属性的顺序来排序的。两个bool类型的成员变量放在前面,两个int类型的成员变量放在后面。

这并不是偶然,我们可以尝试用其他类型的成员变量来代替:

@interface Person : NSObject

@property(非原子,分配)双a;

@property(非原子,分配)BOOL b;

@property(非原子,分配)int c;

@property(非原子,分配)BOOL d;

@结尾

ivar 名称:_b 编码:B 偏移量:8

ivar 名称:_d 编码:B 偏移量:9

ivar 名称:_c 编码:i 偏移量:12

ivar name: _a encode: d offset: 16 还是可以发现,两个bool类型变量放在前面,后面是int,最后是double类型(占用8个字节)。

可以发现一个规律,系统会优化成员变量的排序,将占用内存量小的放在前面,占用内存量大的放在后面。那么系统为什么需要进行这样的优化呢?

0x03 原因

为了尽可能节省对象的内存使用。

这话怎么说呢?为什么这样的安排可以节省对象的内存使用呢?

仍然以Person为例,当我们初始化一个对象Person *p=[[Person alloc] init];时,就会在堆中创建一个对象。这个对象本质上是一个结构体,p指针会指向这个结构体。对象的结构大致如下:

//优化:

结构体Person_obj {

类*isa;

布尔_b;

布尔_d;

int _a;

int _c;

};

//未优化:

结构体Person_obj {

类*isa;

int _a;

布尔_b;

int _c;

布尔_d;

};接下来,让我们打印这两个结构占用了多少内存。

类型定义结构{

类*isa;

布尔_b;

布尔_d;

int _a;

int _c;

}Person_Objc_1;

类型定义结构{

类*isa;

int _a;

布尔_b;

int _c;

布尔_d;

}Person_Objc_2;

NSLog(@"Person_Objc_1====%lu", sizeof(Person_Objc_1));

NSLog(@"Person_Objc_2====%lu", sizeof(Person_Objc_2));

//输出

Person_Objc_1====24

Person_Objc_2====24Eh?不是一样大小吗?有没有区别?

其实不是,这是内存对齐造成的。具体原因将在后面讨论。我们可以先删除isa指针,然后再次打印。

类型定义结构{

布尔_b;

布尔_d;

int _a;

int _c;

}Person_Objc_1;

类型定义结构{

int _a;

布尔_b;

int _c;

布尔_d;

}Person_Objc_2;

NSLog(@"Person_Objc_1====%lu", sizeof(Person_Objc_1));

NSLog(@"Person_Objc_2====%lu", sizeof(Person_Objc_2));

//输出

Person_Objc_1====12

Person_Objc_2====16 嗯,这次有区别。事实上,优化后的结构占用的内存更少。

现在我们知道如何优化系统并了解优化的效果。那么,现在有两个问题:

为什么优化后内存占用变小了?为什么上例中有isa指针时看不到效果呢?

0x04 内存对齐

其实上面两个问题都是同一个原因造成的:内存对齐。

内存对齐的原则:

对于结构体(struct)(或联合体)的数据成员,第一个数据成员放置在偏移量0处,后续每个数据成员存储的起始位置必须从该成员的大小或该成员子的大小开始成员(只要成员有子成员,如数组、结构体等),都是从整数倍开始(例如int在32位机器上是4个字节,必须从4 的整数倍地址。如果结构体成员中有某些项,则结构体成员应从最大内部元素大小的整数倍地址开始存储(struct a 包含struct b)。并且b有char、int、double等元素,那么b应该从8的整数倍开始存储。)结构体的总大小,也就是sizeof的结果,必须是整数倍其最大的内部成员的不足,相信你和我一样,读完之后还是一头雾水。让我们看一个例子。这是没有isa指针时的内存布局:

类型定义结构{

布尔_b; //0-1

布尔_d; //1-2

int _a; //4-8

int _c; //8-12

}Person_Objc_1;

//由于原则1,_a 需要从其大小的整数倍开始存储。

//因此,_a的位置是4-8而不是2-6,而2-4段实际上是空的。

//同时,由于原则3,整体的大小是最大成员的整数倍。

//这正好是12,因此满足了原则3。

类型定义结构{

int _a; //0-4

布尔_b; //4-5

int _c; //8-12

布尔_d; //12-13

}Person_Objc_2;

//由于原则1,_c 需要从其大小的整数倍开始存储。

//因此,_c的位置是8-12而不是5-9,5-8段实际上是空的。

//同时,由于原则3,整体的大小是最大成员的整数倍。

//这里是13,不满足原则3,所以16需要向上取整,所以13-16为空。接下来我们看一下有isa时的布局:

类型定义结构{

类*isa; //0-8

布尔_b; //8-9

布尔_d; //9-10

int _a; //12-16

int _c; //16-20

}Person_Objc_1;

类型定义结构{

类*isa; //0-8

int _a; //8-12

布尔_b; //12-13

int _c; //16-20

布尔_d; //20-21

}Person_Objc_2;

用户评论

罪歌

终于找到关于学习 iOS 基础知识的好文章了!我对类成员变量的存储管理一直很感兴趣,感觉这篇帖子能帮我解决很多疑惑

    有14位网友表示赞同!

屌国女农

要成为优秀的iOS开发者,确实需要牢固掌握底层的知识,类的成员变量优化很重要啊!

    有10位网友表示赞同!

一笑傾城゛

内存优化是我在开发过程中经常会遇到的难题,希望能从这篇文章中学到一些实用技巧

    有11位网友表示赞同!

荒野情趣

这篇标题很有吸引力,应该能让我对类成员变量的内存分配和管理有一个更清晰的理解

    有5位网友表示赞同!

烬陌袅

iOS 开发需要不断学习进步,掌握基础知识永远都不会过时!

    有7位网友表示赞同!

风中摇曳着长发

学习 iOS 时,经常会遇到各种内存问题,看了这篇文章之后或许可以少犯一些错误

    有11位网友表示赞同!

念安я

对程序性能优化一直很重视,这篇文章希望能给我一些有用的经验

    有8位网友表示赞同!

我要变勇敢℅℅

感觉最近的 iOS 开发课程讲得越来越深入,我也开始关注内存管理相关的知识了

    有14位网友表示赞同!

喜欢梅西

学习编程是一段持续的旅程,这次也要好好学习一下类成员变量的内存优化

    有5位网友表示赞同!

熏染

分享这种关于 iOS 基础知识的文章真的很棒!希望有更多这样的文章能帮助到我们

    有8位网友表示赞同!

余温散尽ぺ

相信这篇文章能让我对 iOS 开发的底层机制更加了解

    有13位网友表示赞同!

厌归人

我一直想提高自己的iOS开发技能,这篇文章就恰好解决了我的一个疑问

    有11位网友表示赞同!

如你所愿

最近在开发项目时遇到了内存问题,或许这篇文章能提供一些解决方案

    有7位网友表示赞同!

仅有的余温

学习编程不仅要掌握理论知识,还要注重实际操作,这篇文章正好可以帮助我实践一下

    有7位网友表示赞同!

命运不堪浮华

iOS 开发越来越流行,学习相关的基础知识变得更加重要了

    有15位网友表示赞同!

眼角有泪°

希望这篇文章能够讲解清楚类成员变量内存优化的方法步骤,方便我们理解和应用

    有8位网友表示赞同!

大王派我来巡山!

对编程入门者来说,理解类成员变量的内存管理至关重要,这篇文章能起到很好的指引作用

    有5位网友表示赞同!

妄灸

iOS 开发是个充满挑战但也充满乐趣的过程,期待从中学习到更多。

    有18位网友表示赞同!

玻璃渣子

感谢作者分享这种实用的知识,相信这对很多 iOS 开发者都有帮助!

    有9位网友表示赞同!

【深入解析iOS开发:类成员变量的内存管理策略】相关文章:

1.动物故事精选:寓教于乐的儿童故事宝库

2.《寓教于乐:精选动物故事助力儿童成长》

3.探索动物旅行的奇幻冒险:专为儿童打造的童话故事

4.《趣味动物刷牙小故事》

5.探索坚韧之旅:小蜗牛的勇敢冒险

6.传统风味烤小猪,美食探索之旅

7.探索奇幻故事:大熊的精彩篇章

8.狮子与猫咪的奇妙邂逅:一场跨界的友谊故事

9.揭秘情感的力量:如何影响我们的生活与决策

10.跨越两岸:探索彼此的独特世界

上一篇:感恩田小姐:一场温馨的相遇 下一篇:2017年回顾:每一步坚实足迹