C++ 可算是一种声名在外的编程语言了。这个名声有好有坏,从好的方面讲,C++ 性能非常好,哪个编程语言性能好的话,总忍不住要跟 C++ 来单挑一下;从坏的方面讲,它是臭名昭著的复杂、难学、难用。
当然,这样一来,熟练的 C++ 程序员也就自然而然获得了“水平很高”的名声,所以这也不完全是件坏事。不管说 C++ 是好还是坏,不可否认的是,C++ 仍然是一门非常流行且非常具有活力的语言。继沉寂了十多年,并终于发布语言标准的第二版“C++11”之后,C++ 以每三年一版的频度发布着新的语言标准,每一版都在基本保留向后兼容性的同时,提供着改进和新功能。
正文
C++ 程序员应该都听到过下面这种说法:C++ 是一门多范式的通用编程语言。
多范式,是因为 C++ 支持面向过程编程,也支持面向对象编程,也支持泛型编程,新版本还可以说是支持了函数式编程。同时,上面这些不同的范式,都可以在同一项目中组合使用,这就大大增加了开发的灵活性。因此,C++ 适用的领域非常广泛,小到嵌入式,大到分布式服务器,到处可以见到 C++ 的身影。
C++有着许多著名的应用场景:
1.大型桌面应用程序(如 Adobe Photoshop、Google Chrome 和 Microsoft Office
2.大型网站后台(如 Google 的搜索引擎)游戏(如 StarCraft)和游戏引擎(如 Unreal 和 Unity)
4.视觉和智能引擎(如 OpenCV、TensorFlow)数据库(如 Microsoft SQL Server、MySQL 和 MongoDB)
有些同学可能会觉得,这些应用场景似乎和平时的开发场景有点远啊!你的感觉是对的。有些传统上使用 C++ 的场合现在已经不一定使用 C++,最典型的是个人电脑上的桌面应用。以前 Windows 下开发桌面应用常常用 MFC,微软的 C++ 框架,而现在我估计听说过 MFC 的程序员都不多吧。目前很流行的 Visual Studio Code 主要是用 TypeScript 写的,不是 C++。而我自己也用 C# 写过桌面应用,不过界面逻辑之外的计算和处理仍然是用一个 C++ 的 DLL 来完成。典型情况是,需要性能的组件用 C++ 来写,整个应用程序融合多种不同的语言。
C++ 的传统领域有被侵蚀的风险,那是因为和它相竞争的语言远远不止一个,可以说是上下夹攻。
如果专注性能和最小内存占用的话,C 仍然是首选——嵌入式领域用 C 非常多,而 Linux 也是用纯 C 写的。如果专注抽象表达和可读性的话,那 Python 之类的脚本语言则要方便得多。图形界面(GUI)编程传统上是 C++ 的地盘,但近年来 C# 和 JavaScript 占领了很大一部分市场。游戏算是 C++ 的经典强项了,但有了 C++ 写的游戏引擎,游戏用 C# 写也没啥问题了——你可能不一定知道,Unity 游戏引擎上的首选开发语言是 C#,而王者荣耀是用什么游戏引擎呢?答案正是 Unity——所以王者荣耀可以认为是用 C# 开发的。还有,Go 和 Rust 也加入了战团,对 C++ 形成了一定的竞争。
而随着移动设备的普遍使用,大量设备用电池供电而不接电源了,功耗就逐渐成了我们大家关注的大问题。因此,即使主流移动平台的开发语言不是 C++——而是 Java 和 Objective-C 或 Swift,但任何性能要求高的应用,都几乎必然会用到 C++ 开发的组件。同时,移动设备要联网,也大大刺激了服务器的增加。
在服务器端,虽然没有电池电量的问题,但有着服务器集群的供电问题、空调问题、需要的服务器数量问题等,因而 C++ 的使用也是非常广泛的。前面说到了王者荣耀的客户端是用 Unity + C# 开发的,但我没有说王者荣耀的服务器端——那可还是用 C++ 开发的。
另外,虽然王者荣耀初期是纯用 Unity 开发的,没有用到 C++;但后来,腾讯又用 C++ 把游戏的逻辑部分独立成了一个 GameCore,进一步提高了性能 。目前,跟 C++ 定位差不多、能有直接竞争关系的,也就是既支持高度抽象、又追求高性能的通用编程语言,其实只有 Rust 一种。而 Rust 远没有达到跟 C++ 一样的成熟和普及程度。
另外,和 C 的兼容性,也是 C++ 的一大优势。虽然现在很多大型程序都混杂了多种语言,但在小项目里,减少语言的数量可以简化开发和部署。前不久,我在 Python 里做了一些加解密运算,发现使用的第三方库性能仍不够高,虽然它已经用了 C 开发的加解密引擎。所以,我找了用 C 写的高性能加解密代码,然后使用 pybind11 库,只手写了一百来行的 C++11 代码,就把性能又提高了几倍。
那么,什么时候应该用C++呢?
如此说来,C++ 既然性能又好,又支持抽象,为什么没有更流行呢?
因为代价更高。C++ 是一种复杂的语言,难以上手和熟练掌握,因此也是一种比较容易出错、被误用的语言。C++ 一直与 C 基本保持了向后兼容性,这种兼容性,也一直是 C++ 的安全性和易用性方面的负担。C++ 比起 C 来,要更安全,更不容易出现缓冲区溢出这类漏洞,但跟没有指针概念的语言比起来,它仍然是一种“不安全”的语言。我的个人经验,完成同样的功能,C++ 需要的代码行数一般是 Python 的三倍左右,而性能则可以达到 Python 的十倍以上。
那么问题来了:你在开发上额外付出的时间,能从性能上省回来吗?
显然,这取决于你开发软件的用途和开发时间。举个例子,如果你用 Python 开发需要一天,运行需要十秒,并且不需要反复运行;那么,转用 C++ 开发就意味着开发费用也许要增加两倍,开发加运行的总时间增加两天,大亏。
反之,如果用 Python 开发还是需要一天,单次运行需要十秒,但是软件会作为服务长时间运行、每天被调用十万次。在这种情况下,明显你就需要多台服务器来支撑其使用了。这时,如果用 C++ 开发会需要额外的两天,但跟 Python 相比,部署上有望节约十分之九的硬件和电费——那就很值了。简言之,当你的软件属于运算密集或者内存密集型,你需要性能、且愿意为性能付出额外代价的时候,应该考虑用 C++,特别在你的代码需要部署在多台服务器或者移动设备的场合。反之,如果性能不会成为你开发的软件的瓶颈,那 C++ 可能就不是一个最合适的工具。
此外,在嵌入式应用的场景,那就根本不是值不值、而是行不行的问题。如果程序完成一个功能不能在指定的若干毫秒、甚至微秒内完成,那产品根本是失败、不可用的。在这种场合,能和 C++ 竞争的只有 C,但 C 是一种开发效率更低、更需要堆人力的语言了。
在嵌入式开发使用 C++ 的最大障碍可能不是技术,而是人力资源——搞嵌入式开发的程序员可能大多都习惯使用纯 C 了。由于 C++ 是解决性能问题的利器,短时间里在市场上没有真正的竞争对手,对 C++ 的需求会在相当长的时间里一直存在,尤其在大公司和像金融机构一样对性能渴求的地方。