C++ #pragma once vs 包含守卫?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1143936/
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
#pragma once vs include guards?
提问by Matt Price
I'm working on a codebase that is known to only run on windows and be compiled under Visual Studio (it integrates tightly with excel so it's not going anywhere). I'm wondering if I should go with the traditional include guards or use #pragma once
for our code. I would think letting the compiler deal with #pragma once
will yield faster compiles and is less error prone when copying and pasting. It is also slightly less ugly ;)
我正在研究一个已知只能在 Windows 上运行并在 Visual Studio 下编译的代码库(它与 excel 紧密集成,所以它不会去任何地方)。我想知道我是否应该使用传统的包含守卫或#pragma once
用于我们的代码。我认为让编译器处理#pragma once
会产生更快的编译,并且在复制和粘贴时更不容易出错。它也稍微不那么丑;)
Note: to get the faster compile times we could use Redundant Include Guardsbut that adds a tight coupling between the included file and the including file. Usually it's ok because the guard should be based on the file name and would only change if you needed to change in the include name anyways.
注意:为了获得更快的编译时间,我们可以使用冗余包含保护,但这会增加包含文件和包含文件之间的紧密耦合。通常没问题,因为保护应该基于文件名,并且只有在您无论如何需要更改包含名称时才会更改。
采纳答案by Brian R. Bondy
I don't think it will make a significant difference in compile time but #pragma once
is very well supported across compilers but not actually part of the standard. The preprocessor may be a little faster with it as it is more simple to understand your exact intent.
我认为它不会对编译时间产生重大影响,但#pragma once
在编译器之间得到很好的支持,但实际上并不是标准的一部分。预处理器可能会更快一点,因为它更容易理解您的确切意图。
#pragma once
is less prone to making mistakes and it is less code to type.
#pragma once
不太容易出错,并且需要输入的代码更少。
To speed up compile time more just forward declare instead of including in .h files when you can.
要加快编译时间,只需向前声明,而不是在可能的情况下将其包含在 .h 文件中。
I prefer to use #pragma once
.
我更喜欢使用#pragma once
.
See this wikipedia article about the possibility of using both.
回答by Cookie
I just wanted to add to this discussion that I am just compiling on VS and GCC, and used to use include guards. I have now switched to #pragma once
, and the only reason for me is not performance or portability or standard as I don't really care what is standard as long as VS and GCC support it, and that is that:
我只是想添加到这个讨论中,我只是在 VS 和 GCC 上编译,并且曾经使用过包含守卫。我现在已经切换到#pragma once
,对我来说唯一的原因不是性能、可移植性或标准,因为只要 VS 和 GCC 支持,我真的不在乎标准是什么,那就是:
#pragma once
reduces possibilities for bugs.
#pragma once
减少出现错误的可能性。
It is all too easy to copy and paste a header file to another header file, modify it to suit ones needs, and forget to change the name of the include guard. Once both are included, it takes you a while to track down the error, as the error messages aren't necessarily clear.
很容易将一个头文件复制并粘贴到另一个头文件中,修改它以满足自己的需要,而忘记更改包含保护的名称。一旦两者都包含在内,您需要一段时间来跟踪错误,因为错误消息不一定很清楚。
回答by zwol
#pragma once
has unfixablebugs. It should never be used.
#pragma once
有无法修复的错误。它不应该被使用。
If your #include
search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h
and b/foo.h
), so a #pragma once
in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h"
and #include "../a/foo.h"
refer to the same file, so #pragma once
will fail to suppress a redundant include when it should have.
如果您的#include
搜索路径足够复杂,编译器可能无法告诉用相同的基本名称(例如,两个头部之间的差异a/foo.h
和b/foo.h
),所以#pragma once
他们在一个将抑制两种。它也可能无法分辨出两个不同的相对包含(例如#include "foo.h"
,#include "../a/foo.h"
引用同一个文件,因此#pragma once
在它应该包含的时候无法抑制冗余包含。
This also affects the compiler's ability to avoid rereading files with #ifndef
guards, but that is just an optimization. With #ifndef
guards, the compiler can safely read any file it isn't sureit has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers dodefine the same guard macro, the programmer can go in and change one of them.
这也会影响编译器避免使用#ifndef
守卫重读文件的能力,但这只是一种优化。有了#ifndef
守卫,编译器可以安全地读取它不确定已经看到的任何文件;如果它是错误的,它只需要做一些额外的工作。只要没有两个头文件定义相同的保护宏,代码就会按预期编译。如果两个标头确实定义了相同的保护宏,则程序员可以进入并更改其中之一。
#pragma once
has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once
, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.
#pragma once
没有这样的安全网——如果编译器对头文件的身份有误,无论哪种方式,程序都将无法编译。如果您遇到此错误,您唯一的选择是停止使用#pragma once
,或重命名其中一个标题。标头的名称是 API 合同的一部分,因此重命名可能不是一种选择。
(The short version of why this is unfixableis that neither the Unix nor the Windows filesystem API offer any mechanism that guaranteesto tell you whether two absolute pathnames refer to the same file. If you are under the impression that inode numbers can be used for that, sorry, you're wrong.)
(为什么这是不可修复的简短版本是Unix 和 Windows 文件系统 API 都没有提供任何机制来保证告诉您两个绝对路径名是否指向同一个文件。如果您认为 inode 编号可用于那个,对不起,你错了。)
(Historical note: The only reason I didn't rip #pragma once
and #import
out of GCC when I had the authority to do so, ~12 years ago, was Apple's system headers relying on them. In retrospect, that shouldn't have stopped me.)
(历史注释:我没有撕裂的唯一原因#pragma once
和#import
出GCC的时候,我不得不这样做的权力,〜12年前,是依靠他们苹果的系统头回想起来,不应该停在我身上。)
(Since this has now come up twice in the comment thread: The GCC developers did put quite a bit of effort into making #pragma once
as reliable as possible; see GCC bug report 11569. However, the implementation in current versions of GCC can still failunder plausible conditions, such as build farms suffering from clock skew. I do not know what any other compiler's implementation is like, but I would not expect anyone to have done better.)
(因为这现在在评论线程中出现了两次:GCC 开发人员确实付出了相当多的努力来使#pragma once
尽可能可靠;请参阅GCC 错误报告 11569。但是,当前版本的 GCC 中的实现仍然可能在合理的情况下失败条件,例如构建农场遭受时钟偏差。我不知道任何其他编译器的实现是什么样的,但我不希望有人做得更好。)
回答by Klaim
Until the day #pragma once
becomes standard (that's not currently a priority for the future standards), I suggest you use it AND use guards, this way:
在这一天#pragma once
成为标准之前(目前这不是未来标准的优先事项),我建议您使用它并使用警卫,这样:
#ifndef BLAH_H
#define BLAH_H
#pragma once
// ...
#endif
The reasons are :
原因是:
#pragma once
is not standard, so it is possible that some compiler don't provide the functionality. That said, all major compiler supports it. If a compiler don't know it, at least it will be ignored.- As there is no standard behavior for
#pragma once
, you shouldn't assume that the behavior will be the same on all compiler. The guards will ensure at least that the basic assumption is the same for all compilers that at least implement the needed preprocessor instructions for guards. - On most compilers,
#pragma once
will speed up compilation (of one cpp) because the compiler will not reopen the file containing this instruction. So having it in a file might help, or not, depending on the compiler. I heard g++ can do the same optimization when guards are detected but it have to be confirmed.
#pragma once
不是标准的,因此某些编译器可能不提供该功能。也就是说,所有主要的编译器都支持它。如果编译器不知道它,至少它会被忽略。- 由于 没有标准行为
#pragma once
,您不应该假设所有编译器的行为都相同。守卫将至少确保所有编译器的基本假设是相同的,这些编译器至少为守卫实现了所需的预处理器指令。 - 在大多数编译器上,
#pragma once
将加快编译(一个 cpp),因为编译器不会重新打开包含此指令的文件。因此,将它放在文件中可能会有所帮助,也可能不会,具体取决于编译器。我听说 g++ 可以在检测到守卫时做同样的优化,但必须确认。
Using the two together you get the best of each compiler for this.
将两者结合使用,您可以获得每个编译器的最佳效果。
Now, if you don't have some automatic script to generate the guards, it might be more convenient to just use #pragma once
. Just know what that means for portable code. (I'm using VAssistX to generate the guards and pragma once quickly)
现在,如果您没有一些自动脚本来生成守卫,那么使用#pragma once
. 只要知道这对可移植代码意味着什么。(我正在使用 VAssistX 快速生成守卫和编译指示)
You should almost always think your code in a portable way (because you don't know what the future is made of) but if you really think that it's not meant to be compiled with another compiler (code for very specific embedded hardware for example) then you should just check your compiler documentation about #pragma once
to know what you're really doing.
您几乎应该总是以可移植的方式思考您的代码(因为您不知道未来是由什么组成的)但是如果您真的认为它不打算用另一个编译器编译(例如非常特定的嵌入式硬件的代码)那么你应该检查你的编译器文档#pragma once
以了解你真正在做什么。
回答by Konrad Kleine
From a software tester's perspective
从软件测试人员的角度
#pragma once
is shorter than an include guard, less error prone, supported by most compilers, and some say that it compiles faster (which is not true [any longer]).
#pragma once
比包含保护更短,更不容易出错,大多数编译器都支持,有人说它编译得更快(这不是真的[不再])。
But I still suggest you go with standard #ifndef
include guards.
但我仍然建议你使用标准的#ifndef
包含守卫。
Why #ifndef
?
为什么#ifndef
?
Consider a contrived class hierarchy like this where each of the classes A
, B
, and C
lives inside its own file:
考虑一个人为的类层次结构是这样,每个班的A
,B
和C
它自己的文件里的生活:
a.h
啊
#ifndef A_H
#define A_H
class A {
public:
// some virtual functions
};
#endif
b.h
哈
#ifndef B_H
#define B_H
#include "a.h"
class B : public A {
public:
// some functions
};
#endif
c.h
ch
#ifndef C_H
#define C_H
#include "b.h"
class C : public B {
public:
// some functions
};
#endif
Now let's assume you are writing tests for your classes and you need to simulate the behaviour of the really complex class B
. One way to do this would be to write a mock classusing for example google mockand put it inside a directory mocks/b.h
. Note, that the class name hasn't changed but it's only stored inside a different directory. But what's most important is that the include guard is named exactly the same as in the original file b.h
.
现在让我们假设您正在为您的类编写测试,并且您需要模拟真正复杂的类的行为B
。一种方法是使用例如google mock编写一个模拟类并将其放入目录中。请注意,类名没有改变,但它只存储在不同的目录中。但最重要的是包含保护的命名与原始文件中的完全相同。mocks/b.h
b.h
mocks/b.h
模拟/ bh
#ifndef B_H
#define B_H
#include "a.h"
#include "gmock/gmock.h"
class B : public A {
public:
// some mocks functions
MOCK_METHOD0(SomeMethod, void());
};
#endif
What's the benefit?
有什么好处?
With this approach you can mock the behaviour of class B
without touching the original class or telling C
about it. All you have to do is put the directory mocks/
in the include path of your complier.
使用这种方法,您可以模拟类的行为,B
而无需触及原始类或讲述C
它。您所要做的就是将目录mocks/
放在编译器的包含路径中。
Why can't this be done with #pragma once
?
为什么不能这样做#pragma once
?
If you would have used #pragma once
, you would get a name clash because it cannot protect you from defining the class B
twice, once the original one and once the mocked version.
如果您使用#pragma once
,您会遇到名称冲突,因为它无法防止您B
两次定义类,一次是原始版本,一次是模拟版本。
回答by Donnie DeBoer
If you're positive that you will never use this code in a compiler that doesn't support it (Windows/VS, GCC, and Clang are examples of compilers that dosupport it), then you can certainly use #pragma once without worries.
如果你是积极的,你永远不会在一个编译器使用此代码不支持它(在Windows / VS,GCC,以及锵是编译器的例子也支持它),那么你当然可以使用#pragma一次无后顾之忧.
You can also just use both (see example below), so that you get portability and compilation speedup on compatible systems
您也可以同时使用两者(请参见下面的示例),以便在兼容系统上获得可移植性和编译速度
#pragma once
#ifndef _HEADER_H_
#define _HEADER_H_
...
#endif
回答by fluffy
After engaging in an extended discussion about the supposed performance tradeoff between #pragma once
and #ifndef
guards vs. the argument of correctness or not (I was taking the side of #pragma once
based on some relatively recent indoctrination to that end), I decided to finally test the theory that #pragma once
is faster because the compiler doesn't have to try to re-#include
a file that had already been included.
在进行了关于#pragma once
和#ifndef
守卫之间假设的性能权衡与正确与否的论点的扩展讨论之后(我站在了#pragma once
一些相对最近的灌输的基础上),我决定最终测试#pragma once
更快的理论因为编译器不必尝试重新#include
包含已包含的文件。
For the test, I automatically generated 500 header files with complex interdependencies, and had a .c
file that #include
s them all. I ran the test three ways, once with just #ifndef
, once with just #pragma once
, and once with both. I performed the test on a fairly modern system (a 2014 MacBook Pro running OSX, using XCode's bundled Clang, with the internal SSD).
为了测试,我自动生成了 500 个具有复杂相互依赖性的头文件,并有一个.c
包含#include
所有这些的文件。我以三种方式运行测试,一次使用 just #ifndef
,一次使用 just #pragma once
,一次使用两者。我在一个相当现代的系统上进行了测试(运行 OSX 的 2014 MacBook Pro,使用 XCode 的捆绑 Clang,带有内部 SSD)。
First, the test code:
一、测试代码:
#include <stdio.h>
//#define IFNDEF_GUARD
//#define PRAGMA_ONCE
int main(void)
{
int i, j;
FILE* fp;
for (i = 0; i < 500; i++) {
char fname[100];
snprintf(fname, 100, "include%d.h", i);
fp = fopen(fname, "w");
#ifdef IFNDEF_GUARD
fprintf(fp, "#ifndef _INCLUDE%d_H\n#define _INCLUDE%d_H\n", i, i);
#endif
#ifdef PRAGMA_ONCE
fprintf(fp, "#pragma once\n");
#endif
for (j = 0; j < i; j++) {
fprintf(fp, "#include \"include%d.h\"\n", j);
}
fprintf(fp, "int foo%d(void) { return %d; }\n", i, i);
#ifdef IFNDEF_GUARD
fprintf(fp, "#endif\n");
#endif
fclose(fp);
}
fp = fopen("main.c", "w");
for (int i = 0; i < 100; i++) {
fprintf(fp, "#include \"include%d.h\"\n", i);
}
fprintf(fp, "int main(void){int n;");
for (int i = 0; i < 100; i++) {
fprintf(fp, "n += foo%d();\n", i);
}
fprintf(fp, "return n;}");
fclose(fp);
return 0;
}
And now, my various test runs:
现在,我的各种测试运行:
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.164s
user 0m0.105s
sys 0m0.041s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.140s
user 0m0.097s
sys 0m0.018s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.193s
user 0m0.143s
sys 0m0.024s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE
folio[~/Desktop/pragma] fluffy$ ./a.out
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.153s
user 0m0.101s
sys 0m0.031s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.170s
user 0m0.109s
sys 0m0.033s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.155s
user 0m0.105s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.153s
user 0m0.101s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.181s
user 0m0.133s
sys 0m0.020s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c > /dev/null
real 0m0.167s
user 0m0.119s
sys 0m0.021s
folio[~/Desktop/pragma] fluffy$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin17.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
As you can see, the versions with #pragma once
were indeed slightly faster to preprocess than the #ifndef
-only one, butthe difference was quite negligible, and would be far overshadowed by the amount of time that actually building and linking the code would take. Perhaps with a large enough codebase it might actually lead to a difference in build times of a few seconds, but between modern compilers being able to optimize #ifndef
guards, the fact that OSes have good disk caches, and the increasing speeds of storage technology, it seems that the performance argument is moot, at least on a typical developer system in this day and age. Older and more exotic build environments (e.g. headers hosted on a network share, building from tape, etc.) may change the equation somewhat but in those circumstances it seems more useful to simply make a less fragile build environment in the first place.
正如您所看到的,与-only的版本#pragma once
相比,确实比#ifndef
-only版本的预处理速度略快,但差异可以忽略不计,并且实际构建和链接代码所需的时间会远远超过它。也许对于足够大的代码库,它实际上可能会导致几秒钟的构建时间差异,但是在能够优化的现代编译器之间#ifndef
守卫,操作系统具有良好的磁盘缓存的事实,以及存储技术不断提高的速度,似乎性能论据没有实际意义,至少在当今时代的典型开发人员系统上。较旧和更奇特的构建环境(例如托管在网络共享上的头文件、从磁带构建等)可能会稍微改变等式,但在这些情况下,首先简单地创建一个不那么脆弱的构建环境似乎更有用。
The fact of the matter is, #ifndef
is standardized with standard behavior whereas #pragma once
is not, and #ifndef
also handles weird filesystem and search path corner cases whereas #pragma once
can get very confused by certain things, leading to incorrect behavior which the programmer has no control over. The main problem with #ifndef
is programmers choosing bad names for their guards (with name collisions and so on) and even then it's quite possible for the consumer of an API to override those poor names using #undef
- not a perfect solution, perhaps, but it's possible, whereas #pragma once
has no recourse if the compiler is erroneously culling an #include
.
事实是,#ifndef
标准行为是标准化的,而#pragma once
不是,并且#ifndef
还处理奇怪的文件系统和搜索路径的#pragma once
极端情况,而可能会因某些事情而变得非常困惑,导致程序员无法控制的错误行为。主要的问题#ifndef
是程序员为他们的守卫选择了不好的名字(包括名字冲突等等),即使这样,API 的使用者也很有可能使用#undef
- 这不是一个完美的解决方案,但有可能,而#pragma once
如果编译器错误地剔除#include
.
Thus, even though#pragma once
is demonstrably (slightly) faster, I don't agree that this in and of itself is a reason to use it over #ifndef
guards.
因此,即使#pragma once
明显(稍微)更快,我也不同意这本身就是使用它而不是#ifndef
守卫的理由。
EDIT: Thanks to feedback from @LightnessRacesInOrbit I've increased the number of header files and changed the test to only run the preprocessor step, eliminating whatever small amount of time was being added in by the compile and link process (which was trivial before and nonexistent now). As expected, the differential is about the same.
编辑:感谢@LightnessRacesInOrbit 的反馈,我增加了头文件的数量并将测试更改为仅运行预处理器步骤,消除了编译和链接过程添加的任何少量时间(这在之前和之前都是微不足道的)现在不存在了)。正如预期的那样,差异大致相同。
回答by Michael Burr
I generally don't bother with #pragma once
as my code sometimes does have to compile with something other than MSVC or GCC (compilers for embedded systems don't always have the #pragma).
我通常不会打扰,#pragma once
因为我的代码有时必须使用 MSVC 或 GCC 以外的其他东西进行编译(嵌入式系统的编译器并不总是具有#pragma)。
So I have to use #include guards anyway. I could also use #pragma once
as some answers suggest, but there doesn't seem to be much reason and it will often cause needless warnings on the compilers that don't support it.
所以无论如何我都必须使用#include 守卫。我也可以#pragma once
按照一些答案的建议使用,但似乎没有太多理由,而且它通常会在不支持它的编译器上引起不必要的警告。
I'm not sure what time savings the pragma might bring. I've heard that compilers generally already recognize when a header has nothing but comments outside of the guard macros and will do the #pragma once
equivalent in that case (ie., never processing the file again). But I'm not sure if it's true or just a case of compilers coulddo this optimization.
我不确定 pragma 可能会节省多少时间。我听说编译器通常已经识别出头文件除了保护宏之外的注释之外什么都没有,并且#pragma once
在这种情况下会做等效的事情(即,不再处理文件)。但我不确定这是真的还是只是编译器的一个例子可以做这个优化。
In either case, it's just easier for me to use #include guards which will work everywhere and not worry about it further.
在任何一种情况下,我都更容易使用 #include 守卫,它可以在任何地方工作,而不必再担心。
回答by Motti
There's an related questionto which I answered:
#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
确实有一个缺点(除了非标准),那就是如果您在不同的位置有相同的文件(我们有这个是因为我们的构建系统会复制文件),那么编译器会认为这些是不同的文件。
I'm adding the answer here too in case someone stumbles over this question and not the other.
我也在此处添加答案,以防有人偶然发现这个问题而不是另一个问题。
回答by Richard Corden
I think the first thing you should do is check to see if this is really going to make a difference, ie. you should first test the performance. One of the searches in google threw up this.
我认为您应该做的第一件事是检查这是否真的会有所作为,即。您应该首先测试性能。谷歌中的一项搜索抛出了这个。
In the results page, the columns are sligthly off for me, but it's clear that at least up to VC6 microsoft was not implementing the include guard optimisations that the other tools were using. Where the include guard was internal it took 50 times as long compared with where the include guard was external (external include guards are at least as good as #pragma). But let's consider the possible affect of this:
在结果页面中,列对我来说略微关闭,但很明显,至少在 VC6 之前,微软没有实施其他工具正在使用的包含保护优化。包含保护在内部的情况下,与包含保护在外部的情况相比,它花费了 50 倍的时间(外部包含保护至少与 #pragma 一样好)。但让我们考虑一下这可能产生的影响:
According to the tables presented, the time to open the include and check it is 50 times that of a #pragma equivalent. But the actual time to do so was measured at 1 microsecond per file back in 1999!
根据提供的表格,打开包含并检查它的时间是#pragma 等效项的 50 倍。但在 1999 年,实际这样做的时间是每个文件 1 微秒!
So, how many duplicate headers will a single TU have? This depends on your style, but if we say that an average TU has 100 duplicates then in 1999 we're potentially paying 100 microseconds per TU. With HDD improvements this is probably significantly lower by now, but even then with precompiled headers and correct dependency tracking the total cumulative cost of this for a project is almost certainly an insigificant part of your build time.
那么,单个 TU 将有多少个重复的标头?这取决于您的风格,但如果我们说平均 TU 有 100 个重复项,那么在 1999 年我们可能会为每个 TU 支付 100 微秒。随着 HDD 的改进,现在这可能会显着降低,但即使有了预编译的头文件和正确的依赖项跟踪,项目的总累积成本几乎肯定是构建时间的微不足道的一部分。
Now, on the flip side, as unlikely as it may be, if you ever move to a compiler that doesn't support #pragma once
then consider how much time will it take to update your entire source base to have include guards rather than #pragma?
现在,另一方面,尽管不太可能,但如果您迁移到不支持的编译器,#pragma once
那么请考虑更新整个源代码库以包含保护而不是#pragma 需要多长时间?
There is no reason that Microsoft could not implement an include guard optimisation in the same way that GCC and every other compiler does (actually can anybody confirm if their more recent versions implement this?). IMHO, #pragma once
does very little other than limit your choice of alternative compiler.
微软没有理由不能像 GCC 和其他所有编译器那样实现包含保护优化(实际上任何人都可以确认他们的最新版本是否实现了这一点?)。恕我直言,#pragma once
除了限制您选择替代编译器之外,几乎没有什么作用。