Dmi*_*ich 1 c++ precompiled-headers visual-c++
我所有的问题都与 vc++ 编译器有关,但我猜其他 c++ 编译器具有相同的行为。
//stdafx.h
#include <boost/variant/variant.hpp>
//test1.cpp
#include "stdafx.h"
#include <boost/variant/variant.hpp>
...
//test2.cpp
#include "stdafx.h"
...
Run Code Online (Sandbox Code Playgroud)
我对 VC++ 的内脏没有特别的了解。然而,有了一些编译器设计和理论的知识,这些所谓的“预编译头”就不仅仅是经典编译器设计的初始词法分析和标记化阶段的结果。
考虑一个包含以下内容的简单头文件:
#ifdef FOO
#define BAR 10
#else
#undef FOOBAR
class Foo {
public:
void bar();
};
#include "foobar.h"
#endif
Run Code Online (Sandbox Code Playgroud)
您必须了解使用所谓的“预编译”头文件的效果必须与使用头文件的效果相同。
在这里,你真的不知道这个头文件要做什么。这一切都取决于实际包含头文件时定义的预处理器宏。你不知道这个头文件将定义哪些宏。你不知道这个头文件将取消定义哪些宏。你不知道这个头文件会包含哪些其他头文件。你真的知道的不多,这里。
从概念上讲,要“预编译”头文件,您唯一可以做的就是预解析它。将语言的各个元素、各个关键字(如“#ifdef”、“class”和所有其他内容)转换为单独的二进制标记。删除任何评论,空格等...
编译传统语言的第一阶段涉及将纯文本源解析为内部语言元素。词法分析和标记化阶段。在解析了各个语言元素之后,将尝试弄清楚如何将生成的解析源代码转换为对象模块。这就是编译器 99% 的工作所在。最初的词法分析阶段并不是很多,但这几乎是“预编译”源代码并保存标记化源的内部二进制表示的全部内容,以便可以跳过此阶段,当实际代码使用“预编译”源进行编译。
我假设 VC++ 对预编译头文件的内容几乎没有任何限制。但是,如果有一些限制——比如,预编译头不能有任何条件预处理器指令(ifdef/ifndef),除了经典的守卫——那么就有可能做更多的工作来生成预编译头,并节省一个多一点工作,在这里。对预编译头文件内容的其他限制也可能导致一些附加功能被转移到预编译阶段。