Law*_*and 11 .net c# c++ java compiler-construction
我想知道是什么让主编译器(sun的javac)编译速度如此之快?
..以及Microsoft的C#.NET编译器.
我将它们与C++编译器(例如G ++)进行比较,所以也许我的问题应该是,是什么让C++编译器变得如此缓慢:)
我认为最困难的部分不是需要编译头文件(除非它们非常大,但在这种情况下你可以使用预编译头文件).最糟糕的部分始终是C++的语法对语境过于敏感.尽管我喜欢C++,但我为任何必须编写C++解析器的人感到遗憾.
有几件事使C++编译器比Java/C#慢.语法要复杂得多,通用编程支持在C++中更强大,但同时编译起来更加昂贵.包含文件的工作方式与导入模块的方式不同.
包含头文件
首先,无论何时在C++中包含文件,文件的内容(通常为.h)都会在当前编译单元中注入(包括防护,避免重新注入相同的标头两次),这是可传递的.也就是说,如果你包含头啊,那反过来包括bh,你的编译单元将包含所有代码啊和所有代码bh
Java(或C#,我将谈论Java,但它们在此类似)没有包含文件,它们依赖于编译所用类的二进制文件.这意味着无论何时编译使用b.java中定义的对象B的a.java,它只检查二进制b.class,它不需要更深入地检查B的依赖关系,因此它可以更早地切断进程(只有一个级别的检查).
同时,包含文件只包含语言定义,处理它需要时间.当Java/C#编译器读取二进制文件时,它具有相同的信息,但已经由生成它的编译步骤处理.
所以最后,在C/C++中包含了更多的文件,同时处理这些包含比处理二进制模块更昂贵.
模板
模板以他们自己的方式是特殊的.它们可以预编译,但通常不会(出于一系列原因).这意味着在使用std :: vector的所有编译单元中,处理使用的整个向量方法集(未使用的模板方法不被编译),并且编译器生成二进制代码.在稍后的步骤中,在链接期间,同一方法的冗余定义将被删除,但在编译期间必须处理它们.
Java中对泛型的支持在很多方面受到更多限制.最后,例如,只有一个Vector类二进制文件,每当编译器在java中看到Vector时,它所做的就是在委托给真正的Vector实现(存储普通对象)之前生成类型检查代码,这不是通用的.编译器确实提供类型保证,但不为每种类型编译Vector.
在C#中,它再一次是不同的.对泛型的C#支持比Java更复杂,最后泛型类与普通类不同,但无论如何它们只编译一次,因为二进制格式具有所有必需的信息.