iOS 代码使用 C++ 的 zero-cost abstraction 特性

不少 iOS 项目里都有 C++ 代码的痕迹,Objective-C 和 C++ 虽然都是 C 的 superset,但二者在语言特性上存在很大差异,Objective-C 的 runtime 使其语言的特性更丰富更易使用,但代价是会增加性能损耗以及编译后的 binary size。

很多成熟项目开发到一定阶段,会关注一些关键指标,比如 App size,现在超过 100 M 的 App 比比皆是,而 App Store 上超过 150 MB 的 App 只能通过 Wifi 下载,当常规的瘦身手段用尽之后,App size 每一个 MB 的减少都弥足珍贵,这篇文章向 iOS 开发者介绍 C++ 的 zero cost abstraction 特性,在特定的场景下使用能起到立竿见影的疗效:减小 iOS App 的 binary size,给 App 瘦身。 zero-cost abstraction

Objective-C 和 C++ 同为面向对象语言,我们通过对象来抽象世界中的概念,但 Objective-C 的抽象伴随着代价,抽象越多,定义的类越多,最后编译出的 binary size 也就越大,而 C++ 却没这方面的烦恼,无论你定义多少类,设计多少 component,采用多少设计模式,并不会增加最后的 binary size,也就是所谓的 zero-cost,对 iOS 开发者来说,这种理论听起来可能有些反常识,但如果你是先学习 C, C++,再接触 Objective-C 的 runtime,理解起来再直白不过。

举例来说,假设我们从服务器收到一段请求 user 信息的 response,一般我们会将 response 还原成一个业务 model 对象,user 类的定义如下:

class User { int gender; int age };

如果使用 C++ 来定义这个类,在 C++ 编译器的眼里,这个类的全部信息不过是两个连续存在于内存空间上的 4 个字节(假设一个 int 占 4 字节)。我们访问 user 对象的代码:

int age = user->age;

会被编译器翻译成一段类似如下的内存访问代码:

r11 = *(r10 + 0x4)

在编译器眼里没有类的概念,只有内存地址,偏移量,以及读写操作。即使我们加入更多的抽象,比如把 User 类放进 Car 类里面,再把 Car 放进 City 类里,当我们使用 city->car->user->age 时,编译器依旧会将代码翻译成直白的 memory access。

如果我们使用 Objective-C 来书写上述代码,情况就完全不一样了,熟悉 Objective-C runtime 的同学明白接下来会发生一系列操作,编译后的代码里,Objective-C 的 runtime 会先尝试给 user 对象发送 message(如果是通过 property 访问),需要通过 user 对象的 isa 指针找到 User 类定义,再通过 selector 在 cache 里找到 IMP 地址,最后才从函数返回需要操作的目标内存地址。我只列出了关键的几步,中间其实省略了 n 个流程,类越多,抽象的层次越多,步骤也就越多,这是由于 Objective-C 需要将 class 的定义编译进最后的 binary 里,需要依赖 class 的信息来实现 runtime 的一些机制,class 越多,最后生成 binary 自然也就越大。

简而言之,大部分编程语言和 Objective-C 类似,由于需要在 binary 中保存 class 的信息,而将抽象的成本带入了编译后的机器码。通过上面的分析我们也不难发现 zero-cost abstraction 的好处体现在两方面,一是 binary 更小,二是运行时更高效(没有一层层的中转)。

C++ 的 zero-cost 特性得益于编译器的高效实现,我们在代码里定义的所有类,最后都会被编译器降维,高楼被夷为平地,信息却不会丢失,编译器用一片二向箔将面向对象的世界压扁成一幅画,画里的机器码仍然能严格准确的表达我们的意图。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android机动车

Java 基础(一)——重新理解面向对象

如何利用对象完成真正有用的工作呢?必须有一种办法能向对象发出请求,令其做一些实际的事情。接口就是对一个对象的行为进行规范,使对象具有做某些事情的能力。

751
来自专栏

消失的魔术:隐藏在js引用和原型链背后的超级能力

js这门语言有很多诟病,然而很多被无视的点,构成了js最为美妙的语言特性。这篇文章将带你走进魔术般的引用型数据类型和原型链背后,寻找那些被遗忘的超能力。并且,基...

1192
来自专栏Java呓语

简单工厂模式(选择产品)

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。

791
来自专栏腾讯移动品质中心TMQ的专栏

小说书架内容质量自动化测试

一.项目背景 小说书架的产品思路是:在手机QQ浏览器这个平台上,给用户提供一个小说书架这样的小说阅读入口。通过这个入口阅读到的小说,是后台将从其它网页中抽取到...

2435
来自专栏三木的博客

Kobject浅析

面向对象的思想的确在应用软件的开发中颇具优势,它让一个个纯逻辑的函数和数据变成了一个个有生命的个体。鉴于性能的考虑,系统软件的实现(例如linux kernel...

2068
来自专栏我杨某人的青春满是悔恨

程序设计思维

《SICP》的全名是《Structure and Interpretation of Computer Programs》,中文译名《计算机程序的构造与解释》。...

2384
来自专栏养码场

若你想入职面试阿里系公司,不妨看看这位资深Java的面试经

上上周分享了占小狼面试阿里系的面经文章:《一位资深Java的阿里系公司实战面试经验,套路还是面试官的多》 ,蛮受大家欢迎的。看到大家在社群里的好评与点赞,占小狼...

2072
来自专栏大数据钻研

告诉你学习Java的必要性

Java应该是软件开发同学最熟悉的一种开发语言,古老但很流行,再加上现在android开发发展形势一片大好,更让Java的魅力十足。不少同学想参加Java培训,...

3117
来自专栏web编程技术分享

从啥也不会到可以胜任最基本的JavaWeb工作,推荐给新人的学习路线(二)

3335
来自专栏同步博客

设计模式六大原则

  单一职责原则又称为单一功能原则,即不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

824

扫码关注云+社区

领取腾讯云代金券