#include会影响程序大小吗?

时间:2009-10-08 18:25:37

标签: c++ compilation

当我的cpp文件使用#include添加一些标题时,我的最终程序的大小是否会变大?标头不被视为编译单元,但是头文件的内容由预处理器添加到实际的源文件中,因此输出文件(exe或dll)的大小是否会受此影响?

编辑:我忘了提到问题不在于模板/内联函数。我的意思是如果我将#include放在一个没有任何函数实现细节的头文件中会发生什么。感谢

8 个答案:

答案 0 :(得分:10)

这取决于内容以及编译器的实现方式。很可能如果你不在头文件中使用任何东西,你的编译器就会足够智能,不会将任何内容添加到你的可执行文件中。

然而,我不会指望这一点。我知道回到VC ++ 6天后,我们发现,只有#includingWindows.h为每个执行它的源文件添加64K到excecutable。

答案 1 :(得分:6)

你澄清说:

  

[标题没有]模板/内联函数...没有任何函数的实现细节。

一般来说,不,添加头文件不会影响程序大小。

你可以测试一下。获取已构建的程序,并检查可执行文件的大小。然后进入每个.cpp文件并包含该文件中实际不需要的标准C或C ++头文件。构建程序并再次检查可执行文件大小 - 它应该与之前的大小相同。

总的来说,影响可执行文件大小的唯一因素是导致编译器生成不同数量的代码,全局/静态变量初始化或DLL /共享库使用的那些。即便如此,如果该程序不需要任何此类项目,大多数现代链接器都会抛弃这些东西。

因此,包含只包含函数原型,没有内联的类/结构定义以及枚举定义等内容的头文件不应该改变任何内容。

然而,肯定有例外。以下是一些。

一个是你有一个简单的链接器。然后,如果你添加一个生成程序实际上不需要的东西的头文件,并且链接器不会抛出它们,那么可执行文件的大小就会膨胀。 (有些人故意以这种方式构建链接器,因为链接时间可能变得非常快。)

很多时候,添加添加或更改预处理程序符号定义的头文件会改变编译器生成的内容。例如,assert.h(或cassert)定义了assert()宏。如果在.c / .cpp文件中包含一个更改NDEBUG预处理程序符号定义的头文件,它将更改assert()用法是否生成任何代码,从而更改可执行文件大小。

此外,添加更改编译器选项的头文件将更改可执行文件大小。例如,许多编译器允许您通过类似 #pragma pack 行更改结构的默认“打包”。因此,如果添加一个更改.c / .cpp文件中的结构打包的头文件,编译器将生成用于处理结构的不同代码,从而更改可执行文件大小。

正如其他人所指出的那样,当你处理Visual C ++ / Visual Studio时,所有的赌注都没有了。对于他们的开发工具,微软有一个独特的视角,在其他平台上编写编译系统的人不会分享这些视角。

答案 2 :(得分:1)

使用包含现代编译器的文件只会影响二进制文件的大小(如果它们包含静态数据)或者使用其中定义的普通函数或内联函数。

答案 3 :(得分:0)

是的,因为例如可以在头文件中定义内联函数,并且当您调用这些函数时,这些内联函数的代码将被添加到程序的代码中。此外,模板实例化也会添加到程序代码中。

答案 4 :(得分:0)

您还可以在头文件中定义全局变量(虽然我不推荐它)。如果这样做,你应该用#ifdef / #end blocks包围它们,这样它们就不会在多个编译单元中被定义(或链接器会抱怨)。无论如何,这会增加程序的大小。

答案 5 :(得分:0)

对于完全声明的标题(通常应该是这样),没有。但是,预处理器和编译器必须花时间来解析头,因此头可以增加编译时间;特别是大而深度嵌套的 - 例如 - 这就是为什么有些编译器使用'预编译头'。

即使内联和模板代码也不会直接增加代码大小。如果模板从未实例化或未调用内联函数,则不会生成代码。但是,如果调用/实例化,代码大小可以快速增长。如果编译器实际内联代码(编译器没有义务这样做,并且大多数情况除非被强制执行),代码重复可能很重要。即使它没有被编译器真正内联,它仍然在引用它的每个对象模块中静态实例化 - 它需要一个智能链接器来删除重复项,并且这不是给定的 - 如果是单独的对象使用不同的选项编译文件,来自同一源的内联代码可能不会在每个目标文件中生成相同的代码,因此甚至不会重复。对于模板,将为每个调用的类型创建单独的实例化。

答案 6 :(得分:0)

请记住,#define句子可以在编译时将代码膨胀为一个巨大但功能强大的编译文件。

答案 7 :(得分:0)

优良作法是将文件中的#include限制为必要的。除了影响可执行文件的大小之外,如果你更改了一个常见的#included头文件,那么额外的#includes会导致更大的编译时依赖项列表,这会增加你的构建时间。