没有输出的输入是不完整的

0%

为什么c++比java运行的速度快

最近和同学讨论算法题目的时候,突然讲到为什么java的速度比c++慢,当时一知半解,雾里看花。
于是回来之后查了一下资料,整理一下放在这里,方便以后查看。
暂时理解到这个程度,如果以后有新的理解再做补充。

明确原则

首先,不能认为c++在所有程序中都比java快:

不同的语言和实现各有取舍,具体速度要结合程序和运行环境来判断。

java替我们处理了很多实现细节,用起来比较方便;c++则允许我们直接控制更多细节,为特定问题选择合适的实现方式。这些选择也会影响程序的开销。

比如我们在使用java语言的时候,方法参数统一按值传递;对于对象参数,复制的是对象引用的值。方法中可以通过这个引用修改对象,但把参数指向另一个对象,不会改变调用者变量的指向。但是我们如果使用的是c++,那么就可以选择传值、传指针值或者传引用,根据不同的选择在方法内部也有不同的使用方式。

原因浅析

编译过程不一样

在前面我们已经介绍过c++ 的编译过程,g++编译器可以直接将我们的源码编译成为机器可以执行的二进制代码(机器指令的集合),从而直接执行。

而对于java语言,java编译器会将java源码编译成字节码(独立于CPU架构,cpu不认识),然后由JVM加载。以HotSpot为例,代码可以先解释执行,热点代码再由JIT编译成当前cpu架构的机器指令,之后直接执行这些机器指令。

字节码方便java程序在不同的机器上运行,而JVM启动和JIT预热也会带来开销。热点编译完成后,执行效率则取决于生成的机器指令和优化效果。

对象的创建不同

从JVM的抽象内存模型来看,对象位于堆中,局部变量可以保存对象的引用,访问对象可能涉及间接寻址。不过,HotSpot还会做逃逸分析和标量替换,可以消除一些new出来的对象的实际分配,减少这部分开销。

而在c++ 中,很多普通局部变量和对象通常保存在栈中,也可能被优化到寄存器中;通过new创建的对象则使用动态存储。程序员可以根据对象的使用方式和生命周期来选择。

检查机制不同

java虚拟机本身在运行时会对程序进行很多的检查,比如说检查数组越界,检查类型是否错误,检查是否空指针,检查对象是否需要回收(JVM)等等,比较充分地保证了java程序的安全性和稳定性,也可能带来检查开销;其中一些检查可以在JIT证明安全后消除。

而在c++程序中,普通数组和裸指针的很多操作不会自动做边界检查,需要程序员保证使用正确,否则越界等操作可能产生未定义行为。

所以实际比较时,还是要注明具体程序、编译器和优化参数,区分java的启动时间和JIT预热后的执行时间,再通过测量判断。

参考

  1. java运行速度比C++慢的原因
  2. 知乎-为什么说 Java 比 C / C++ 慢?
  3. Oracle:Java HotSpot 性能优化与逃逸分析