编译器每次编译主程序时都会编译所有包含的头文件吗
Does compiler compiles all included header files along with the main program every time we compile that program?
根据维基百科,这就是C预处理器所做的:
"预处理器用文件'
stdio.h
'的文本替换行#include <stdio.h>
,其中声明了printf()
函数等。">
如果这是真的,那么一个包含更多头文件的程序将需要更多的时间来编译?
因此,如果这是真的,那么一个包含更多标头的程序文件的编译会花费更多时间吗?
当然。严格地说,编译器需要查看的代码越多,处理它所需的时间就越多。对于一些真正大的项目来说,查看所有文件所需要的时间很容易成为一个问题。对于非常大和/或复杂的模板代码尤其如此,因为实际原因,这些代码必须位于头文件中。头文件本身的组织也会对编译时间产生影响。
然而,它并不像你想象的那么简单。它高度依赖于编译器的实现质量(QOI),而现代编译器实际上在大多数情况下都非常擅长处理头文件。
例如,GCC特别认可包含保护以减少处理时间。如今的编译器在处理复杂的模板代码方面做得越来越好,例如大多数标准库。根据我的经验,在VC++编译器上,包括windows.h
(它几乎为整个Windows API提供了函数原型)并没有明显增加编译时间。如果其他一切都失败了,那么即使不是所有编译器,也有许多编译器都可以使用"预编译头"功能。
基本上,在它成为问题之前不要担心它。如果拥有更多的头文件有助于更好地组织代码,那么无论如何都要毫不犹豫地使用它们。
通常是的,“包含更多头文件的程序将需要更多的时间来编译。";。
不幸的是,标头的预处理内容可能会根据定义的宏符号和方式而有所不同。尤其是Microsoft的标头通常被设计为,以根据这些符号产生不同的结果(在标准C++中,它主要只是NDEBUG
符号,这会影响assert
的扩展)。因此,编译器是保守的,并对每个翻译单元进行一次又一次的预处理和头编译。
避免这种情况的一种常见技术是所谓的预编译头。
据我所知,一种不常见的技术,可能没有被任何编译器实现,是允许程序员说"对于这批编译,你可以假设所有的头都将扩展到相同的",甚至可以将其作为默认(即使在假设不成立的情况下,可以产生与标准C++不同的结果)。
我非常喜欢后一种方法,因为它可以加快大多数构建的速度,但预编译的头文件是我们在实践中所拥有的。
David Vandevoorde为C++编写了一个模块提案。
带模块的语言示例:Modula-2、Ada、UCSD Pascal。
不幸的是,它还没有为C++11做好准备,但也许我们稍后会得到模块。
理论上是的-代码越多,编译时间越长。您包含的所有内容都是通过预处理器放置的,而不是您已经提到的include语句。
实际上,这取决于你包含了什么以及如何包含。如果你以适当的方式加入,对速度的影响可以忽略不计。包含过多的标准标头会造成名称空间污染,然后会产生编译时问题。标准库的整个代码已经编译完毕,将只进行链接。在Qt中,您可以单独包含每个类(例如#include <QWidget>
),也可以包含模块中的所有类(例如,#include <QtGui>
),该模块包含数千个标头。所以我从来没有注意到两种方法之间有相当大的编译时间差异。
一些想法和事实形成了我的经验:
-
在计算机中提到了收割台防护装置。它们主要不是用于编译时优化,而是用于防止循环包含。所以如果在10个位置包含一个标头,那么它将只被解析一次。
-
在C++中,只有从中的类派生时才包含在头中头球否则使用正向声明。
-
使用私有实现习惯用法-这样您的头将只包含一个/几个指针。
-
不要包含你的代码头,这是你不需要的c/cpp文件。一个好的构建系统分析标头对include语句的基础。您的代码不必要每次必须包含的任何标头发生更改时都会重新编译。
-
除了编译时间外,链接时间也可能相当长。制作当然,该应用程序由DLL(DLL/so文件)组成,因此您可以避免在每次编译时将所有内容链接在一起。在一个项目中,我经历了大约10分钟的连接时间。客户拒绝使用DLL是因为一些深奥的原因。
-
如果编译器时间真的是一个问题,那么值得在构建系统的引擎盖。一些不平凡的项目必须运行编译后/预编译脚本。检查这些脚本的执行情况只有在必要时才执行。
-
在一个项目中,整个构建时间减少了在对制造工具进行一些修改后4小时至40分钟。如果你在Linux上,请与strace核实make是如何工作的。你会的令人惊讶的是,它进行了如此多不必要的文件访问。
- 编译包含字符串的代码时遇到问题
- g++编译包含的头:没有这样的文件或目录
- 包含模板文件的递归会导致编译失败
- 编译包含指向模板函数的指针的初始值设定项列表时,gcc 出错,但 clang 不出错
- 编译包含LLVM API标头的C++文件时出错
- 无法编译包含"if constexpr"的函数模板实例化
- 编译包含 CPLEX 工具的项目时出错
- 如何让 CMake 编译包含 Boost Local Functions 的源文件
- 编译包含结构的h文件时发生链接错误
- 如何使用C++(g++)编译器编译包含C++关键字的C代码
- 编译包含动态并行性的代码失败
- 编译包含文件无法识别的 pro*C 文件时出现编译错误,即使在指定 ProjectDir (Visual Studio
- MSVC2013 无法编译包含巨大查找表的头文件
- 找不到库.正在尝试编译包含Lapack(C++)的程序
- 如何要求Linux g++正确编译包含在另一个头文件中的头文件
- 如何在Visual Studio 2013+中编译包含"interface"作为变量名的程序
- 编译包含exprTk的c++文件的问题
- 如何编译包含C++代码的C代码
- 尝试编译包含二进制 ifstream 的代码时,编译会导致错误
- 编译包含多个文件的程序