C++ 为什么在包含防护装置之前放置#包含

C++ 为什么在包含防护装置之前放置#包含,c++,include,c-preprocessor,spidermonkey,C++,Include,C Preprocessor,Spidermonkey,在头文件中的include卫士之前放置#include指令是否有任何有效的原因,如下所示: #include "jsarray.h" #include "jsanalyze.h" #include "jscompartment.h" #include "jsgcmark.h" #include "jsinfer.h" #include "jsprf.h" #include "vm/GlobalObject.h" #include "vm/Stack-inl.h" #ifndef jsinfe

在头文件中的include卫士之前放置#include指令是否有任何有效的原因,如下所示:

#include "jsarray.h"
#include "jsanalyze.h"
#include "jscompartment.h"
#include "jsgcmark.h"
#include "jsinfer.h"
#include "jsprf.h"
#include "vm/GlobalObject.h"

#include "vm/Stack-inl.h"

#ifndef jsinferinlines_h___
#define jsinferinlines_h___

//main body mostly inline functions 

#endif
注意,这个例子取自一个真实的高姿态开源项目,应该由经验丰富的程序员开发——Firefox10中使用的Mozilla Spidermonkey开源Javascript引擎(最新版本中也存在相同的头文件)


在备受瞩目的项目中,我希望他们的设计背后一定有一些合理的理由。在include guard(包含防护装置)之前设置
#include
的有效原因是什么?它是一种仅适用于内联函数头文件的模式吗?还要注意,这个头文件(jsinferinlines.h)实际上是通过include-guard之前的最后一个
#include“vm/Stack inl.h”
指令(这个头文件包括许多其他头文件,其中一个实际上也包括这个jsinferinlines.h)来包含它自己,这对我来说就更没有意义了。

因为你希望这些标题包含自己的防护,所以这并没有什么区别

还要注意,这个头文件(jsinferinlines.h)实际上是通过include-guard之前的最后一个#include“vm/Stack inl.h”(这个头文件包括许多其他头文件,其中一个实际上又包括这个jsinferinlines.h)指令来包含它自己,这对我来说更没有意义

它不会有任何不同,因为包含该文件时,工作流将:

  • 包括所有标题,直到“vm/Stack inl.h”
  • 包括
    “vm/Stack inl.h”
    到最后一个
    #包括“jsinferinlines.h”
    (您的文件)
  • 再次包含文件
    jsfereinlines.h
    (跳过前面的所有包含,因为包含保护)
  • 超过
    #包括“vm/Stack inl.h”
  • 最后,从

但一般来说,相互头递归是不好的,应该不惜一切代价避免。

那时SpiderMonkey头中有很多include循环,将头保护放在顶部会导致难以理解的编译错误——我怀疑将头保护放在包含之下只是清理包含的一个渐进步骤

但是,我无法告诉你导致它产生影响的确切的包含顺序


现在,SM头中不应该有任何include循环,它们的样式是通过Nicholas Nethercote编写的python脚本来实现的。如果您今天查看jsinferinlines.h,您将看到头保护位于它所属的顶部。

它对编译性能有很大的影响,因为它必须首先打开所有这些文件。(当然,真正的编译器通常会缓存它们,但仍然如此。)如果我们有两个相互包含的文件呢?(我不是在这里讨论这种做法有多糟糕)。在include-guard的正常使用中,当它们是文件中的第一件事时,不会发生任何事情。如果include在防护之前,编译器将进入无限循环。@WojtekSurowka,当然。不过这是你的一个错误。@Jeffrey-如果文件包含自身,现代编译器会做什么?@WojtekSurowka:现代编译器会检测常见的“包含保护”模式,并相应地优化对
fopen
的调用。合法使用包含应该像没有进行优化一样工作(否则这是一个bug),并且应该检测到错误(无限周期等)(否则这是一个bug)。当然,gcc和clang的现代版本应该能够很好地处理这些边缘情况。