c++程序中多个源文件中的相同头文件

same header file in multiple source files in a c++ program

本文关键字:文件 源文件 程序 c++      更新时间:2023-10-16

如果同一个头文件包含在c++程序的多个源文件中,那么它如何影响编译(特别是g++) ?

是编译器只加载头文件一次并为每个包含头文件的源文件编译它,还是头文件将为每个包含它的源文件单独加载

与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文件来完成的;然后在每个文件中首先#include这个文件(或者使用"强制包含"的想法:msvc中的/Fi, gcc中的-include)。使用给定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("%sn", words[i]);
    }
    return 0;
}

输出将是

<>之前你好呸世界呸呸

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

#ifndef MY_HEADER_H
#define MY_HEADER_H
// header body...
#endif MY_HEADER_H

如果没有此保护,头文件可能被包含多次,这可能导致编译或链接错误。

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

预处理器 简单地替换每个源文件中的宏定义,完成后,编译器将开始将每个源文件编译为独立的汇编文件,然后由汇编器翻译成二进制机器码。链接器最后将所有的对象文件链接到一个执行的文件或一个共享对象

所以在预处理过程中,这基本上与编译器无关。g++是一个工具包,包括预处理器,编译器,链接器。