c++程序中多个源文件中的相同头文件
same header file in multiple source files in a c++ program
如果同一个头文件包含在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++是一个工具包,包括预处理器,编译器,链接器。
- 为测试目标创建具有不同源文件夹的文件
- 生成一个生成文件,该生成文件使用Automake在一个步骤中编译和链接所有源文件
- 生成文件:动态源文件名和对象目录
- 无法使用 CMake 从其他文件夹添加源文件
- CMake 源文件找不到头文件
- 给定一个源文件,有没有办法要求 gcc 返回仅直接包含的头文件的列表?
- UE4 - Visual Studio在我从编辑器添加新的c ++文件后无法打开任何源文件 - UBT_COMPILED
- cpp 在主源文件中包括.cpp文件导致错误"duplicate symbol"
- 如何将 .ui 完全转换为 C++ 头文件和源文件
- 在生成文件中添加源文件并更新依赖项
- CMake 在源文件附近找不到头文件
- GNU 在看到其他同名文件时重用源文件
- #include "date.h" 创建错误 E1696 无法打开源文件"date.h",也无法打开包含文件:没有这样的文件或目录
- DirectX 11 文件无法打开源文件
- 用libclang解析源文件 - 链接问题包括文件
- C++ - 定义类模板(头文件/源文件)
- 在使用头文件/源文件时访问类变量的麻烦
- 如何声明和定义全局变量,以便从所有头文件/源文件中正确访问它们
- 将lambda传递给模板类中的方法(头文件/源文件问题)
- LNK 2019/1120我的头文件/源文件实践中的双重链接列表错误