Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c+;中多个源文件中的相同头文件+;程序 如果在C++程序中的多个源文件中包含相同的头文件,那么它对编译(尤其是 G+++ >强> >如何影响?< /P>_C++_Header_G++ - Fatal编程技术网

c+;中多个源文件中的相同头文件+;程序 如果在C++程序中的多个源文件中包含相同的头文件,那么它对编译(尤其是 G+++ >强> >如何影响?< /P>

c+;中多个源文件中的相同头文件+;程序 如果在C++程序中的多个源文件中包含相同的头文件,那么它对编译(尤其是 G+++ >强> >如何影响?< /P>,c++,header,g++,C++,Header,G++,编译器是否只加载一次头文件,并针对包含头文件的每个源文件进行编译,或者针对包含头文件的每个源文件分别加载头文件。大多数头文件都有针对多个包含的特殊保护,如 #ifndef MY_HEADER_H #define MY_HEADER_H // header body... #endif MY_HEADER_H 如果没有此保护,可能会多次包含标头,这可能会导致编译或链接错误 编译器可能足够聪明,可以避免多次读取文件。但是,即使没有,操作系统也非常擅长缓存最近读取的文件,这将非常、非常快地加载—

编译器是否只加载一次头文件,并针对包含头文件的每个源文件进行编译,或者针对包含头文件的每个源文件分别加载头文件。

大多数头文件都有针对多个包含的特殊保护,如

#ifndef MY_HEADER_H
#define MY_HEADER_H

// header body...

#endif MY_HEADER_H
如果没有此保护,可能会多次包含标头,这可能会导致编译或链接错误

编译器可能足够聪明,可以避免多次读取文件。但是,即使没有,操作系统也非常擅长缓存最近读取的文件,这将非常、非常快地加载—几乎没有成本。

对g++:
#include
是由预处理器完成的,而不是编译器本身。使用g++的
-E
开关可以看到预处理的结果。(编辑:前处理器过去是独立的,但现在是编译器可执行文件的一部分,但是为了回答此问题,前处理阶段仍然是编译过程的一个不同阶段)

使用gcc、clang、icc和msvc,每次遇到每个文件时都会访问它,即使是在同一个源文件中

唯一不正确的情况是头文件包含
#pragma once
语句。有些编译器对include guards的用户进行了类似的优化:

#ifndef THIS_FILE_H
#define THIS_FILE_H 1
/* the stuff in thisfile.h */
#endif
msvc和gcc(可能还有clang)支持一种称为“预编译头”的技术,它将与您一起工作,以避免一组常用头的编译头

通常,这是通过在.h或.cpp文件中包含所有的
#include
s来实现的;然后在每个文件中首先包含该文件(或者在msvc中使用“强制包含”。:/Fi,-include with gcc)。使用给定pch的每个文件都必须具有相同的定义和编译器选项

如果要编写以下.h文件

// bah.h
"bah",
和下面的.cpp文件

#include <stdio.h>

const char* words[] = {
    "hello",
#include "bah.h"
    "world",
#include "bah.h"
#include "bah.h"
    NULL
};

int main(int argc, const char* argv[])
{
    for (size_t i = 0; words[i] != NULL; ++i ) {
        printf("%s\n", words[i]);
    }
    return 0;
}
#包括
常量字符*单词[]={
“你好”,
#包括“bah.h”
“世界”,
#包括“bah.h”
#包括“bah.h”
无效的
};
int main(int argc,const char*argv[]
{
for(大小i=0;字[i]!=NULL;++i){
printf(“%s\n”,字[i]);
}
返回0;
}
输出将是

hello bah world bah bah 你好 呸 世界 呸 呸 预处理器将简单地替换每个源文件中的宏定义,完成后,编译器将开始将每个源文件编译成独立的汇编文件,然后由汇编程序将其翻译成二进制机器代码。而链接器将最终将所有对象文件链接到一个执行文件或一个共享对象


因此,在预处理过程中,编译器基本上不需要这样做。而C++是一组工具,包括预处理器、编译器、链接器。实现可能会选择加载一次,按需加载(对于每个源文件),或者以我有限的大脑无法想象的其他奇怪方式加载。基本上
#include*.h
意味着“替换”此处*.h文件中的所有文本。从概念上讲,编译的每个文件都会重新查看标题。实际上,您的编译器很可能支持某种形式的预编译头,因此它会将源代码编译成某种中间形式,然后在编译包含相同头文件的其他文件时使用它。是否有可能g++编译器经过优化,即使从不同的源文件多次调用,也只能加载一次头文件?请确认。@birajbora它绝对可以。预编译头是一种常见的东西,不必在单个进程中存储在内存中。它们可以很容易地写入磁盘,并在以后的过程中使用。如果您阅读了这个问题,它是关于在多个源文件中包含头的。单个源文件中没有多个包含。我很确定你没有回答所问的问题,而是回答了一个完全不同的类似问题。@mvp:是的,与第一次编译代码相比,重新编译速度非常快。“对于
g++
\include
-s是由预处理器完成的”这句话并不完全正确:多年以来,
g++
正在启动
cc1plus
,这是一个单独的程序,用于进行预处理、解析、优化和代码发布。。。。预处理由编译器(
cc1plus
)完成,而不是单独完成。(这是1990年代GCC中的一个独立过程)。据我所知,在开始编译阶段之前,预处理器仍然是一个完整完成的离散过程?这在很久以前是真的。。。而今天是错误的
cc1plus
(来自GCC4.x)正在链接一个内部库
libcpp
,该库进行预处理和一些标记化。而预处理是在(解析之前)以增量方式进行的。。。。GCC不是一次进行预处理,然后解析预处理的表单(即使它似乎是这样工作的)。如果编译器包将每个源文件的相同头文件翻译成编译后的代码,那么代码优化在哪里发生?@birajbora在编译步骤中。我认为优化中的头文件没有多少工作要做。毕竟,所有这些都是需要统一表达式的函数声明、类定义或其他信息。您在头文件中声明了所有函数,并在另一个cc文件中进行了实现。您不想在头文件中实现您的函数,是吗?但是什么时候会发生呢