可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
Is this something that is supported by most modern compilers on non-windows platforms (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?
回答1:
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.
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
.
回答2:
#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.
回答3:
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.
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.
But we have what we have (except that you might not have #pragma once
).
回答4:
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
#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.
回答5:
GCC supports #pragma once
since 3.4, see http://en.wikipedia.org/wiki/Pragma_once for further compiler support.
The big upside I see on using #pragma once
as opposed to include guards is to avoid copy/paste errors.
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.
TL;DR: #pragma once
is easier to use.
回答6:
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.
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.
In the end, using the guard or the pragma, won\'t matter at all.
回答7:
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.
回答8:
Not always.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 has 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).
回答9:
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.
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.
In the end, the better suggestion you can get to 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.
#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).
回答10:
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.
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.
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.
If you do observe a significant speed up, however, please update your question.
回答11:
Today old-school include guards are as fast as a #pragma once. Even if the compiler doesn\'t treat them specially, it will still stop when it sees #ifndef WHATEVER and WHATEVER is defined. Opening a file is dirt cheap today. Even if there were to be an improvement, it would be in the order of miliseconds.
I simply just don\'t use #pragma once, as it has no benefit. To avoid clashing with other include guards I use something like: CI_APP_MODULE_FILE_H --> CI = Company Initials; APP = Application name; the rest is self-explanatory.
回答12:
The main difference is that the compiler had to open the header file to read the include guard. In comparison, pragma once causes the compiler to keep track of the file and not do any file IO when it comes across another include for the same file. While that may sound negligible, it can easily scale up with huge projects, especially ones without good header include disciplines.
That said, these days compilers (including GCC) are smart enough to treat include guards like pragma once. i.e. they dont open the file and avoid the file IO penalty.
In compilers that dont support pragma I\'ve seen manual implementations that are a little cumbersome..
#ifdef FOO_H
#include \"foo.h\"
#endif
I personally like #pragma once approach as it avoids the hassle of naming collisions and potential typo errors. It\'s also more elegant code by comparison. That said, for portable code, it shouldn\'t hurt to have both unless the compiler complains about it.
回答13:
If we use msvc or Qt (up to Qt 4.5), since GCC(up to 3.4) , msvc both support #pragma once
, I can see no reason for not using #pragma once
.
Source file name usually same equal class name, and we know, sometime we need refactor, to rename class name, then we had to change the #include XXXX
also, so I think manual maintain the #include xxxxx
is not a smart work. even with Visual Assist X extension, maintain the \"xxxx\" is not a necessary work.
回答14:
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.