C++ 程序在编写完成或者做了更改后的第一次运行前,需要先编译。C++ 编译的整个过程分为 4 步:
注意在汇编前的程序都是文本,经过汇编,就转换为了二进制文件,C++ 中常说的机器码就是二进制,二进制文件就可以直接交由计算机运行了。接下来详细讲一下四个步骤中发生了什么:
应用程序包含的是机器码,也就是二进制数据,这些二进制指令是可以直接交由计算机操作的,是一种最底层语言,因此效率很高。而且多次执行相同的程序,只有第一次需要编译。
Python 之所以被称为脚本语言,是因为其不需要在运行前编译,而是在运行过程中“像脚本一样”被解释器逐句转换为机器码(二进制),这样的话相当于每次执行 Python 脚本,都要再进行一次转换为二进制的过程,因此在这一点上 Python 就已经慢了很多。
言归正传,所以这两种语言的效率差异到底体现在什么地方呢?
首先第一点就是上文提到的,每次执行 Python 脚本,都要再由解释器进行一次转换为二进制的过程,而 C++ 只有第一次需要编译,后续都可以直接执行机器码。
这里我们可以举一个例子:
编写 Python 脚本时不需要声明类型,而是交由解释器进行动态类型检查。Python 官方指定的解释器为 CPython,CPython 是基于 C 实现的,在 CPython 中,每个对象底层都是一个 Obj* 指针类型,这个指针可以指向任意一种类型,所以所以它可以指向任意的对象,因此Python无法做基于类型方面的优化。以变量a + b为例,这个a和b指向的对象可以是整型、浮点型、字符串、列表、元组、甚至是我们自己实现了某个方法的类的实例对象。在计算 a+b 时,首先 Python 要判断变量到底指向的是什么类型,这在 C 级至少需要一次属性查找。然后 Python 将每一个操作都抽象成了一个方法,所以实例相加时要在对应的类型对象中找到该方法对应的函数指针,这又是一次属性查找。找到了之后将a、b作为参数传递进去,这会发生一次函数调用,会将 a 和 b 中维护的值拿出来进行运算,然后根据相加结果创建一个新的对象,再返回其对应的 PyObject * 指针。而对于 C++ 来讲,由于已经规定好了类型,所以a + b在编译之后就是一条简单的机器指令,所以两者在效率上差别很大。
第二点是 C++ 在编译阶段是可以进行优化的,C++ 编译器通常默认是 O0 优化,这是使用了最快的编译时间,在这种优化模式下:
O1 优化:
之后还有 O2 和 O3 优化,但是因为这些优化比较激进,会大幅增加编译的时间,而且编译后的文件难以调试,一般比较少用到。
总之,C++ 中存在编译过程的优化,而 Python 并没有,这又在另一个维度上让 C++ 快于 Python。
本文从 C++ 和 Python 的运行过程入手,从编译器和解释器的差异分析了为什么 C++ 会比 Python 的运行速度快。在现代的企业场景中,追求极致代码运算效率的场景通常还是使用的 C++,比如服务器端编程、游戏编程等。