C++编译和文件大小



我已经在谷歌上搜索过了,但大多数结果都是关于编译器A和编译器B的。

这个问题源于我在Web设计方面的经验(知道Web设计中常用的语言是不编译的。CGI是一个例外。)当你在网页中包含文件时,整个文件都会下载到用户的计算机上。如果使用JQuery(一个JavaScript库),则必须在<head>中包含JQuery才能使用其函数。这让我开始思考C++编译器。

在C++中,几乎不可能在没有#include <library>的情况下进行编程。库是否与项目文件一起编译?

例如,在这个简单的Hello Word程序#include <iostream>中,iostream头文件中的所有代码都已编译吗?只使用定义cout的代码并将其添加到本例中会使文件的大小变小吗?编译器优化是否只负责从iostream编译必要的代码?

#include <iostream>
int main()
{
std::cout<<"Hello World.";
return 0;
}

例如,在这个简单的Hello Word程序#include中,iostream头文件中的所有代码都已编译吗?将ONLY作为定义cout的代码并将其添加到本例中会使文件的大小变小吗?编译器优化是否只负责从iostream编译必要的代码?

是和否。C++包含是一个非常简单的机制。included头实际上只是与include文件连接在一起,所以是的,简单的答案是,您可以获得包含的所有内容。

但是,一旦以这种方式包含了所有内容,编译器就会尝试消除所有未使用的位。对于许多(并非所有)标头,这很容易观察到:如果您编译一个简单的Hello World程序,查看文件大小,然后再包含几个标头并重新编译,则可执行文件的大小通常相同(或几乎相同)。编译器确定您包含的大部分cruft从未使用过,并再次将其删除。

但也有例外。例如,某些标头,只要被包含,就会在应用程序启动时运行代码,这意味着即使没有引用标头中包含的任何内容,编译器也无法将其删除。

所有编译器都有自己的STL实现——有些是开源的(gcc),有些只包含头。在大多数情况下,这些实现已经编译到库中,以加快程序的编译过程。标题只是向编译器提示这些编译后的库包含什么——有点像阅读库内容的指南。它们不是自己汇编的。

如果这个库是静态的,那么链接器阶段从库中获取数据并将其复制到可执行文件中。如果它是一个动态库(.dll、.so或.dlib),则不会复制任何数据——您的可执行文件只是在运行时调用这些文件中的数据。这可能是通过函数地址或符号名称实现的,这取决于动态库的链接方式(在大多数情况下是前者)。

编译器有一个优化阶段,可以清除未使用的数据。例如,如果您包含了iostream,但没有使用它的任何内容,那么这些数据都不会链接到您的程序。根据编译器的不同,如果只使用cout::operator<<的一个重载,那么只有该重载及其调用的函数才会被链接。由于STL是一个模板库,所以它是与可执行文件一起编译的。这是因为通常有无限多的可能结果——IEstd::vector采用除引用之外的任何类型,永远无法编译成库,因为它的作用取决于您给它的类型。

MSVC有一个工具,您可以使用它来查看可执行文件的编译程序集及其代码和包含库的代码。如果您使用的是MSVC++2013,那么在进程调试期间按alt-8将启动此工具,称为反汇编程序。如果你有兴趣看到所有这些信息,这是一个可视化程序的好方法。

iostream这样的头定义了各种类型、函数,有时还定义了全局变量。

库文件是预编译的源代码,用于实现头文件的函数/类。cout在头文件中定义,但驻留在库中。

通常,编译器会确保只添加程序运行所需的代码位。然而,在某些情况下,#include确实会使代码变得更大。一种这样的情况是,如果库使用内联代码,这确实会增加大小。

库是预编译的。您的程序与库相链接。(类似于运行时c++库)

如果使用静态库,链接器会将使用的方法复制到可执行文件中。

如果您使用共享库(so、DLL等),它会在可执行文件中保存对链接方法的引用,而不是复制到可执行文件。

包含文件不是预编译的。它们由类或库的某些API组成。通常只是方法的原型,但有时是所有的源(如模板类)使用#include宏意味着将整个头文件复制到源文件中。

编译过程中还有一些步骤:

  1. 预处理-将所有包含文件添加到位。宏解析等。输出是一个更大的源文件,可以编译
  2. compile-将每个源文件编译为机器语言,输出二进制文件(对象文件)
  3. 链接-获取所有已编译的文件和所有使用的库,并生成可执行文件

编译器编译所有源代码,但在链接中,链接器只获取使用的代码,并将其添加到可执行文件中,无论代码是在头中的源代码中还是在库中。如果它没有被使用,它就不会被添加到可执行文件中。

最新更新