【问题标题】:#include <iostream> in C++?#include <iostream> 在 C++ 中?
【发布时间】:2017-04-28 05:28:03
【问题描述】:

我读到#include &lt;file&gt; 会在编译之前通过 C++ 预处理器将粘贴的“文件”复制到我们的源文件中。

这是否意味着只要我们编译源文件,“文件”(iostream)也会一次又一次地编译?

同样在C++完成它的工作之后,中间文件的大小也会有“文件”+“源文件大小”的字节数吗?

【问题讨论】:

  • 上一个关于同一主题的问题可以帮助你很多stackoverflow.com/questions/22645097/…
  • 阅读preprocessor 的文档(C 和 C++ 几乎相同,但配置不同)。如果使用GCC(例如g++)编译器,您可以像-H一样传递preprocessor options(以了解真正包含哪些标头),或者使用-C -E获取预处理表单
  • 可能值得一提的是“forward declaration”标头,尤其是iosfwd,它类似于缩小尺寸的iostream,当您不需要完整iostream 的所有细节时很有用文件。

标签: c++


【解决方案1】:

我读到#include &lt;file&gt; 会复制 在被 C++ 预处理器粘贴“文件”到我们的源文件中之前 编译。

是的。编译器正确看到的数据将由file 中的数据和源文件中的数据组成。 (实际上,如今真正的编译器倾向于将 C 预处理器、编译器前端和编译器后端合并到一个程序中——但这几乎是一个细节。)

这是否意味着“文件”(iostream)也将被再次编译 并且只要我们编译源文件?

是的。一些编译器有一个称为“预编译头文件”的特性,它允许你编译一堆头文件,然后多次使用它的输出。你如何做到这一点因编译器而异;如果您需要可移植性,请不要担心(它不会对编译时间产生太大影响)。

同样在 C++ 完成它的工作之后,中间文件的大小也会 有“文件”+“源文件大小”的字节?

没有。输出文件的大小与源文件的大小只有非常微弱的关系。例如#include &lt;iostream&gt; 定义了许多 许多 内联函数。任何特定的程序只会使用其中的一小部分——因此它们将从编译器输出中省略。

注释(使用源文件中的空间)不会出现在输出中。

另一方面,如果您编写一个复杂的模板,然后为几种不同的类型实例化它,那么输出将包含每种类型的模板的不同副本,并且可能比输入大很多。

【讨论】:

  • 我按照 Shubham 所说的做了...写了一个大小为 77 字节的 hello world 代码...预处理代码的大小为 428282 字节...汇编版本的大小为 1745 字节,目标代码的大小为 2480 bytes.想知道 iostream 头文件的大小是多少。
  • 请注意,iostream 本身很可能很小 - 但它会包含许多其他文件。
【解决方案2】:

关于中间文件大小的大小,是的,它会增加。您可以通过编写一个简单的 hello world 程序来检查这一点,然后按如下方式编译它(在 Linux 中)

g++ name.cpp -o name --save-temps

这将存储中间文件,具体来说:

"name.ii" (Preprocessed code after including <iostream>
"name.s"  (Assembly version of the code)
"name.o"  (Object code)

使用以下方法检查此文件大小的差异:

ls -l name.cpp name.ii

【讨论】:

  • 嗯。编译需要#include 文件(在这种情况下,如果不包含它,则不会成为输出文件),或者不需要它(在这种情况下,我会感到惊讶通过#include 设法增加.o 文件的大小 - 是的,我可以构建反例,但它们非常人为)。
  • @MartinBonner 对不起,我不明白。你能再解释一下吗?我所知道的是,在编译之前,预处理器会复制源文件中所有包含的头文件,然后编译这个文件。这就是为什么我说大小会增加,因为正在编译中间源文件。但是我不确定这个中间源文件的所有未使用的功能是否都包含在程序集中以及随后的目标代码中。
  • “文件大小会增加” - 我认为这是指“如果包含头文件,输出文件的大小会比不包含头文件时更大”。我不认为这是真的。如果您的意思是“由于包含文件,输出文件的大小将大于输入文件的大小”,我认为这也不正确。输入和输出文件的大小只是非常弱相关。
  • 好吧,预处理后的源文件至少会比 iostream 大,但目标文件可能不会更大(但如果你使用 LTO 的话)。两者都可以被认为是 ›中间文件‹。
  • @MartinBonner 可能不会,但相关的初始化和销毁​​代码可能 > 1 字节:)
【解决方案3】:

No.libraries(headers) 不要增加文件的大小,因为编译器不会将所有标题添加到您的代码中。它只是将您在代码中使用的东西添加到您的代码中,

【讨论】:

    【解决方案4】:

    不,它不会增加程序大小。文件 iostream 和许多其他头文件没有可编译的语句。它们包含您的程序所需的一些定义。 如果您查看经过预处理的 C/C++ 文件,您会看到在文件开头添加了数千个定义。

    你可以用 cpp 工具试试,像普通的 g++/gcc 一样用命令运行它,然后查看输出。

    cpp -I /usr/include/ -I.文件.cpp -o 文件.预处理

    它只包含标题和定义,它们不会增加最终程序的大小。

    编辑: 正如马丁所说,它们具有可编译的内联函数,每次都会编译,但除非您使用它们,否则它们不会增加您的程序大小。

    【讨论】:

    • iostream 肯定确实有可编译的语句!定义(尤其是内联函数和模板)可编译的 - 如果使用它们会增加程序的大小。
    【解决方案5】:

    我读到 #include 会将粘贴“文件”复制到我们的源中 编译前由 C++ 预处理器生成的文件。

    比这更微妙一点。 #include "file" 按照您的描述进行。 #include &lt;file&gt; 引入了一个 header,它不需要是一个文件。这个想法是编译器可以有自己的内部版本的头文件,已经是二进制形式,所以它不必读取和解析文件。如果没有具有该名称的标头,则它将 include 指令视为 #include "file" 并查找要读取的文件。

    实际上,我不知道有哪个编译器可以利用这种余地;事实上,所有头文件都是一遍又一遍地编译的文件。但是,正如其他人所说,这本身并不意味着可执行文件变大。理想情况下,如果您不使用它,它不会进入可执行文件,尽管有些系统在这方面比其他系统更好。

    【讨论】:

    • 我认为有一个 IBM 编译器有一个用于标准库头文件的数据库?它可能是一个 C 编译器。
    • @MartinBonner - 你是对的,我忘记了这一点。但它并没有很好地工作,这就是它不再存在的原因。
    猜你喜欢
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多