C++ #pragma 曾经是一个安全的包含守卫吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/787533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is #pragma once a safe include guard?
提问by Ryan Emerle
I've read that there is some compiler optimization when using #pragma once
which can result in faster compilation. I recognize that is non-standard, and thus could pose a cross-platform compatibility issue.
我读过使用时有一些编译器优化#pragma once
可以导致更快的编译。我认识到这是非标准的,因此可能会造成跨平台兼容性问题。
Is this something that is supported by most modern compilers on non-windows platforms (gcc)?
这是非 Windows 平台 (gcc) 上的大多数现代编译器都支持的吗?
I want to avoid platform compilation issues, but also want to avoid the extra work of fallback guards:
我想避免平台编译问题,但也想避免后备保护的额外工作:
#pragma once
#ifndef HEADER_H
#define HEADER_H
...
#endif // HEADER_H
Should I be concerned? Should I expend any further mental energy on this?
我应该担心吗?我应该在这上面花费更多的精神能量吗?
采纳答案by Zifre
Using #pragma once
should work on any modern compiler, but I don't see any reason not to use a standard #ifndef
include guard. It works just fine. The one caveat is that GCC didn't support #pragma once
before version 3.4.
使用#pragma once
应该适用于任何现代编译器,但我认为没有任何理由不使用标准#ifndef
包含保护。它工作得很好。一个警告是 GCC#pragma once
在3.4 版之前不支持。
I also found that, at least on GCC, it recognizes the standard #ifndef
include guard and optimizes it, so it shouldn't be much slower than #pragma once
.
我还发现,至少在 GCC 上,它识别标准#ifndef
include guard 并对其进行优化,因此它不应该比#pragma once
.
回答by Motti
#pragma once
does have one drawback (other than being non-standard) and that is if you have the same file in different locations (we have this because our build system copies files around) then the compiler will think these are different files.
#pragma once
确实有一个缺点(除了非标准),那就是如果您在不同的位置有相同的文件(我们有这个是因为我们的构建系统会复制文件),那么编译器会认为这些是不同的文件。
回答by Michael Burr
I wish #pragma once
(or something like it) had been in the standard. Include guards aren't a real big deal (but they do seem to be a little difficult to explain to people learning the language), but it seems like a minor annoyance that could have been avoided.
我希望#pragma once
(或类似的东西)一直在标准中。包含守卫并不是什么大不了的事(但他们似乎有点难以向学习该语言的人解释),但这似乎是一个可以避免的小烦恼。
In fact, since 99.98% of the time, the #pragma once
behavior is the desired behavior, it would have been nice if preventing multiple inclusion of a header was automatically handled by the compiler, with a #pragma
or something to allow double including.
事实上,由于在 99.98% 的情况下,该#pragma once
行为是所需的行为,如果编译器自动处理防止多次包含头文件,并使用 a#pragma
或其他内容允许双重包含,那就太好了。
But we have what we have (except that you might not have #pragma once
).
但是我们拥有我们所拥有的(除了您可能没有#pragma once
)。
回答by JaredPar
I don't know about any performance benefits but it certainly works. I use it in all my C++ projects (granted I am using the MS compiler). I find it to be more effective than using
我不知道任何性能优势,但它肯定有效。我在所有 C++ 项目中都使用它(当然我使用的是 MS 编译器)。我发现它比使用更有效
#ifndef HEADERNAME_H
#define HEADERNAME_H
...
#endif
It does the same job and doesn't populate the preprocessor with additional macros.
它做同样的工作并且不会用额外的宏填充预处理器。
GCC supports #pragma once
officially as of version 3.4.
GCC从 3.4 版开始#pragma once
正式支持。
回答by uceumern
GCC supports #pragma once
since 3.4, see http://en.wikipedia.org/wiki/Pragma_oncefor further compiler support.
GCC#pragma once
从 3.4 开始支持,请参阅http://en.wikipedia.org/wiki/Pragma_once以获得进一步的编译器支持。
The big upside I see on using #pragma once
as opposed to include guards is to avoid copy/paste errors.
我认为使用#pragma once
而不是包含守卫的最大好处是避免复制/粘贴错误。
Let's face it: most of us hardly start a new header file from scratch, but rather just copy an existing one and modify it to our needs. It is much easier to create a working template using #pragma once
instead of include guards. The less I have to modify the template, the less I am likely to run into errors. Having the same include guard in different files leads to strange compiler errors and it takes some time to figure out what went wrong.
让我们面对现实:我们大多数人几乎不会从头开始创建一个新的头文件,而只是复制现有的头文件并根据需要修改它。使用#pragma once
而不是包含守卫来创建工作模板要容易得多。我修改模板的次数越少,我遇到错误的可能性就越小。在不同的文件中使用相同的包含保护会导致奇怪的编译器错误,并且需要一些时间来找出问题所在。
TL;DR: #pragma once
is easier to use.
TL;DR:#pragma once
更容易使用。
回答by Edwin Jarvis
I use it and I'm happy with it, as I have to type much less to make a new header. It worked fine for me in three platforms: Windows, Mac and Linux.
我使用它并且我对它很满意,因为我必须输入更少的内容来制作新的标题。它在三个平台上对我来说效果很好:Windows、Mac 和 Linux。
I don't have any performance information but I believe that the difference between #pragma and the include guard will be nothing comparing to the slowness of parsing the C++ grammar. That's the real problem. Try to compile the same number of files and lines with a C# compiler for example, to see the difference.
我没有任何性能信息,但我相信 #pragma 和包含守卫之间的区别与解析 C++ 语法的缓慢相比毫无意义。这才是真正的问题。例如,尝试使用 C# 编译器编译相同数量的文件和行,以查看差异。
In the end, using the guard or the pragma, won't matter at all.
最后,使用守卫或编译指示,根本无关紧要。
回答by Jonathan Leffler
Using '#pragma once
' might not have any effect (it is not supported everywhere - though it is increasingly widely supported), so you need to use the conditional compilation code anyway, in which case, why bother with '#pragma once
'? The compiler probably optimizes it anyway. It does depend on your target platforms, though. If all your targets support it, then go ahead and use it - but it should be a conscious decision because all hell will break loose if you only use the pragma and then port to a compiler that does not support it.
使用 ' #pragma once
' 可能没有任何效果(并非所有地方都支持它 - 尽管它得到越来越广泛的支持),因此无论如何您都需要使用条件编译代码,在这种情况下,为什么要使用 ' #pragma once
'?无论如何,编译器可能会对其进行优化。不过,它确实取决于您的目标平台。如果您的所有目标都支持它,那么继续使用它 - 但这应该是一个有意识的决定,因为如果您只使用编译指示,然后移植到不支持它的编译器,那么一切都会崩溃。
回答by Klaim
The performance benefit is from not having to reopen the file once the #pragma once have been read. With guards, the compiler have to open the file (that can be costly in time) to get the information that it shouldn't include it's content again.
性能优势在于一旦读取 #pragma once 就不必重新打开文件。使用守卫,编译器必须打开文件(这在时间上可能很昂贵)以获取不应再次包含其内容的信息。
That is theory only because some compilers will automatically not open files that didn't have any read code in, for each compilation unit.
这只是理论上的,因为对于每个编译单元,某些编译器不会自动打开没有任何读取代码的文件。
Anyway, it's not the case for all compilers, so ideally #pragma once have to be avoided for cross-platform code has it's not standard at all / have no standardized definition and effect. However, practically, it's really better than guards.
无论如何,并非所有编译器都是这种情况,因此理想情况下,跨平台代码必须避免使用 #pragma once 它根本不是标准的/没有标准化的定义和效果。然而,实际上,它确实比警卫好。
In the end, the better suggestion you can getto be sure to have the best speed from your compiler without having to check the behavior of each compiler in this case, is to use both pragma once and guards.
最后,在这种情况下,无需检查每个编译器的行为即可确保从编译器获得最佳速度的更好建议是同时使用 pragma once 和 guards。
#ifndef NR_TEST_H
#define NR_TEST_H
#pragma once
#include "Thing.h"
namespace MyApp
{
// ...
}
#endif
That way you get the best of both (cross-platform and help compilation speed).
这样你就可以充分利用两者(跨平台和帮助编译速度)。
As it's longer to type, I personally use a tool to help generate all that in a very wick way (Visual Assist X).
由于打字时间较长,我个人使用一种工具来帮助以非常好的方式生成所有这些内容(Visual Assist X)。
回答by Omer
Not always.
不总是。
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566has a nice example of two files meant to both be included, but mistakenly thought to be identical because of identical timestamps and content (not identical file name).
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566有一个很好的例子,两个文件都被包含在内,但由于相同的时间戳和内容(不相同的文件名)而被错误地认为是相同的.
回答by Tim Post
Using gcc 3.4 and 4.1 on very large trees (sometimes making use of distcc), I have yet to see any speed up when using #pragma once in lieu of, or in combination with standard include guards.
在非常大的树上使用 gcc 3.4 和 4.1(有时使用distcc),当使用 #pragma once 代替标准包含守卫或与标准包含守卫结合使用时,我还没有看到任何加速。
I really don't see how its worth potentially confusing older versions of gcc, or even other compilers since there's no real savings. I have not tried all of the various de-linters, but I'm willing to bet it will confuse many of them.
我真的不明白它有什么价值可能会混淆旧版本的 gcc,甚至其他编译器,因为没有真正的节省。我还没有尝试过所有的各种 de-linters,但我敢打赌它会混淆他们中的许多人。
I too wish it had been adopted early on, but I can see the argument "Why do we need that when ifndef works perfectly fine?". Given C's many dark corners and complexities, include guards are one of the easiest, self explaining things. If you have even a small knowledge of how the preprocessor works, they should be self explanatory.
我也希望它早点被采用,但我可以看到“当 ifndef 工作得很好时为什么我们需要它?”的论点。鉴于 C 的许多黑暗角落和复杂性,包括守卫是最简单、自我解释的事情之一。如果您对预处理器的工作原理知之甚少,它们应该是不言自明的。
If you do observe a significant speed up, however, please update your question.
但是,如果您确实观察到明显的加速,请更新您的问题。