我读到过,使用#pragma一次可以优化编译器,从而加快编译速度。我知道这是不标准的,因此可能会带来跨平台兼容性问题。

非windows平台(gcc)上的大多数现代编译器都支持这一点吗?

我希望避免平台编译问题,但也希望避免备用保护的额外工作:

#pragma once
#ifndef HEADER_H
#define HEADER_H

...

#endif // HEADER_H

我应该担心吗?我还需要在这上面花费更多的精力吗?


当前回答

Additional note to the people thinking that an automatic one-time-only inclusion of header files is always desired: I build code generators using double or multiple inclusion of header files since decades. Especially for generation of protocol library stubs I find it very comfortable to have a extremely portable and powerful code generator with no additional tools and languages. I'm not the only developer using this scheme as this blogs X-Macros show. This wouldn't be possible to do without the missing automatic guarding.

其他回答

在非常大的树上使用gcc 3.4和4.1(有时使用distcc)时,我还没有看到使用#pragma一次代替或与标准include守卫结合使用时的速度有任何提高。

我真的不认为它值得让旧版本的gcc甚至其他编译器感到困惑,因为它并没有真正的节省。我并没有尝试过所有的去污工具,但我敢打赌它会让很多人感到困惑。

我也希望它能早点被采用,但我能看到“当ifndef工作得很好时,我们为什么需要它?”的争论。考虑到C语言的许多黑暗角落和复杂性,包含警卫是最简单的、自我解释的事情之一。如果你对预处理器的工作方式有一点了解,它们应该是不言自明的。

但是,如果您确实观察到一个显著的加速,请更新您的问题。

我不知道有什么性能上的好处,但它确实有效。我在我所有的c++项目中都使用它(当然我使用的是MS编译器)。我发现它比使用更有效

#ifndef HEADERNAME_H
#define HEADERNAME_H
...
#endif

它做同样的工作,并且不使用额外的宏填充预处理器。

GCC在3.4版正式支持#pragma。

我使用它,我很高兴,因为我必须键入更少,使一个新的标题。它在Windows、Mac和Linux三个平台上都运行得很好。

我没有任何性能信息,但我相信,与解析c++语法的缓慢相比,#pragma和include守卫之间的差异将是微不足道的。这才是真正的问题。例如,尝试用c#编译器编译相同数量的文件和行,看看有什么不同。

最后,使用guard或pragma根本不重要。

使用#pragma一次应该适用于任何现代编译器,但我不认为有任何理由不使用标准的#ifndef include guard。它工作得很好。需要注意的是,GCC在3.4版之前一次都不支持#pragma。

我还发现,至少在GCC上,它可以识别标准的#ifndef include guard并对其进行优化,因此它应该不会比#pragma慢很多。

主要的区别是编译器必须打开头文件来读取包含保护。相比之下,pragma只会导致编译器跟踪该文件,并且在遇到针对同一文件的另一个include时不执行任何文件IO。虽然这听起来可以忽略不计,但它可以很容易地扩展到大型项目,特别是那些没有好的标题包括学科的项目。

也就是说,现在的编译器(包括GCC)足够聪明,可以像对待pragma一样对待include守卫。例如,他们不打开文件,避免文件IO惩罚。

在不支持pragma的编译器中,我见过手动实现有点麻烦。

#ifdef FOO_H
#include "foo.h"
#endif

我个人喜欢#pragma once方法,因为它避免了命名冲突和潜在的拼写错误的麻烦。相比之下,它的代码也更加优雅。也就是说,对于可移植的代码,如果编译器不同意,那么两者都使用也无妨。