#include <iostream> in C++?

7
我读到 #include 会在 C++ 预处理器编译前将 "file" 复制粘贴到我们的源文件中。这是否意味着 "file" (iostream) 也会随着我们编译源文件而一遍又一遍地被编译?
此外,在 C++ 完成其工作后,中间文件的大小是否还包括 "file" 和源文件大小的字节?

同一主题的先前问题可以帮助您很多。https://dev59.com/gGEh5IYBdhLWcg3wPRWq - AurA
阅读预处理器的文档(C和C++的文档几乎相同,但配置不同)。如果使用GCC(例如g++)编译器,则可以传递预处理器选项,如-H(了解实际包含哪些头文件),或者使用-C -E获取预处理后的形式。 - Basile Starynkevitch
值得一提的是"前向声明"头文件,特别是iosfwd,它类似于一个缩小版的iostream,在您不需要完整的iostream文件的所有细节时非常有用。 - R.M.
5个回答

12
我读到了#include <file>会在C++预处理器编译之前将“file”复制并粘贴到我们的源文件中。
是的。编译器实际看到的数据将包括file中的数据和您的源文件中的数据。(实际上,现在的真正编译器 tend 进行将 C 预处理器、编译器前端和编译器后端合成为一个单一程序。但这基本上只是一个细节。)
这是否意味着“file”(iostream)也会随我们编译源文件而一遍又一遍地重新编译?
是的。某些编译器具有称为“预编译头”的功能,允许您编译一堆头文件一次,然后多次使用该输出。如何执行此操作因编译器而异;如果需要可移植性,则不必担心它(这对编译时间的影响并不大)。
此外,在C++完成其工作后,中间文件的大小是否还包括“file”的字节和“源文件的大小”?
不。输出文件的大小与源文件的大小关系极弱。例如,#include <iostream>定义了许多内联函数。任何特定程序仅使用其中很少的几个,因此它们将被省略从编译器输出中去掉。注释(在源文件中使用空间)不会出现在输出中。另一方面,如果您编写了一个复杂的模板,并为几种不同类型进行实例化,则输出将包含每种类型的不同副本,并且可能比输入大得多。

我按照Shubham的指示编写了一个大小为77字节的Hello World代码...预处理后的代码大小为428282字节...汇编版本大小为1745字节,目标代码大小为2480字节。不知道iostream头文件的大小是多少。 - Harsh Pathak
请注意,iostream本身很可能非常小 - 但它将包括许多其他文件。 - Martin Bonner supports Monica

3

关于中间文件大小的问题,是的,它会增加。您可以编写一个简单的 HelloWorld 程序并按以下方式编译它(在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 文件大小感到惊讶 - 是的,我可以构造反例,但它们非常人为)。 - Martin Bonner supports Monica
@MartinBonner 对不起,我没听懂。你能再解释一下吗?我的理解是,在编译之前,预处理器会将源文件中所有包含的头文件复制到该文件中,然后编译该文件。这就是为什么我说大小会增加,因为正在编译中间源文件。但我不确定是否所有未使用的功能都包含在汇编和随后的目标代码中。 - Shubham
预处理后的源代码至少会比iostream的大小更大,但目标文件可能不会更大(如果使用LTO可能会更大)。两者都可以被视为“中间文件”。 - Darklighter
@T.C.:那就是我想到的“人造”情况——我忘记了IOStream实际上使用它!(当然,我认为ios_base::Init没有必要大于1个字节)。 - Martin Bonner supports Monica
1
@MartinBonner 可能不是, 但相关的初始化和销毁代码可能>1字节 :) - T.C.
显示剩余2条评论

0

没有库(头文件)不会增加文件的大小,因为编译器不会将所有头文件添加到您的代码中。它只会将您在代码中使用的内容添加到您的代码中。


0
不会增加程序大小。文件iostream和许多其他头文件没有可编译的语句。它们包含一些程序所需的定义。如果您查看预处理的C/C++文件,您将看到在文件开头添加了数千个定义。
您可以使用cpp工具尝试它,使用类似于正常g++/gcc的命令运行并查看输出。
cpp -I /usr/include/ -I. file.cpp -o file.preprocessed
它只包含头文件和定义,它们不会增加您最终程序的大小。
编辑:正如马丁所说,它们具有可编译的内联函数,每次都会编译,但除非您使用它们,否则它们不会增加您的程序大小。

1
“iostream” 绝对有可编译的语句!定义(特别是内联函数和模板)是可编译的 - 如果使用它们,将会增加程序的大小。 - Martin Bonner supports Monica

0
我了解到 #include 会在 C++ 预处理器编译之前将 "file" 复制粘贴到我们的源文件中。
实际上,情况比这更微妙一些。#include "file" 执行你所描述的操作。#include 引入一个头文件,该文件不一定是必需的。其想法是编译器可以拥有自己内部版本的该头文件,已经以二进制形式存在,因此它不必读取和解析文件。如果没有该名称的头文件,则将包含指令视为 #include "file" 并查找要读取的文件。
实际上,我不知道有哪个编译器利用了这种灵活性;所有的头文件都是被反复编译的文件。但是,正如其他人所说,这本身并不意味着可执行文件变得更大。理想情况下,如果您不使用它,它就不会进入可执行文件,尽管某些系统在这方面做得比其他系统更好。

我记得有一款IBM编译器,它拥有标准库头文件的数据库。可能是一款C编译器。 - Martin Bonner supports Monica
@MartinBonner - 你说得对,我忘记了那个。但它并不是很有效,这就是为什么它已经不存在了。 - Pete Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接