在C++应用程序里不同类型数据进行混合运算时,C++编译器会自动进行类型转换。为了避免不同的数据类型在运算中出现类型问题,应尽量使用同种类型数据,不会使用可提升应用程序性能的特殊指令。
真的是 C++应用程序的性能就一定很差吗?不是的。实际上在这道题中,使用的算法是非常高效的。上面的 0.001 秒和 0.062 秒已经分别是 C/C++ 程序和 C# 程序在 Timus Online Judge 网站运行的最短时间了。毕竟 C# 是托管的应用程序,要在 CLR 环境中运行,***次运行时需要进行 JIT 编译。最小的基本开销要比 C/C++ 应用程序大。
接着,我们再来看看 Timus 1219. Symbolic Sequence:
这道题要求输出满足给定条件的一百万个小写拉丁字母。还是使用同样的算法, C++应用程序比 C#程序慢 15 倍,比 C 程序慢 64 倍。
这次,不能用最小的基本开销来解释了,因为这些程序运行的时间已经不算很短了。但是,这道题还是有些特别的,它的时间主要花费在输出大量的(一百万个)字符上。C# 程序是调用了一百万次 Console.Write() 方法,C++ 程序调用了一百万次 std::cout << c 语句,C 程序调用了一百万次 putchar() 函数。应该是这三种方法的不同效率造成的差异。如果把本题的算法稍做修改,使 C++应用程序只调用一次 Console.Write() 方法输出全部一百万个字符,则其运行时间从 0.968 秒下降到 0.093 秒。
现在,让我们来看看 Timus 1152. The False Mirrors:
这道题说述消灭怪物的故事,要求计算出故事中主角受到的最小伤害。还是使用同样的算法,我们终于看到 C# 程序和 C++ 程序的运行时间差不多了。
不过,坦白的说,实际上这道题我使用的算法不是***的。这道题***的算法使用 C++ 语言实现,运行时间只需要 0.001 秒。我不知道该算法是什么,如有谁知道的麻烦告诉我一下。:)
由于大多数 ACM 题目使用好的算法时需要的时间是很短的,所以如果用 C# 语言做题的话,基本上会发现比 C/C++ 语言慢很多,但是一般来说也不会超时,除非你使用的算法很差。下面就有一个例子,就是 Timus 1081. Binary Lexicographic Sequence:
这道题要求给出第 K (0 < K < 109) 个 N (0 < N < 44) 位二进制数,该二进制数不得有相邻的“1”。在 Accepted 的 C# 和 C++ 程序中,使用了时间复杂度为 O(N) 的算法。而在 Time limit exceeded 的 C++ 程序中,使用了时间复杂度约为 C++应用程序的算法。
何况,托管应用程序的性能在某些应用场合实际上有可能超过非托管的应用程序。例如,当 JIT 编译器在运行时将 IL 代码编译成本地代码时,编译器对执行环境的认识比非托管编译更加深刻。#t#
JIT 编译器能判断应用程序是否运行在一个 Core 2 Duo 的 CPU 上,并生成相应的本地代码来利用 Core 2 Duo 支持的任何特殊指令。通常,非托管应用程序是针对具有最小功能集合的 CPU 编译的,不会使用可提升应用程序性能的特殊指令。