views:

3439

answers:

10

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?

+8  A: 

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 + #define HEADERNAME_H. It does the same job and doesn't populate the preprocessor with additional macros.

GCC supports #pragma once officially as of version 3.4 (Reference).

JaredPar
+11  A: 

It 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.

Edit: 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. source

Zifre
It shouldn't be any slower at all (with GCC anyway).
Jason Coco
I haven't done any tests, so I wasn't exactly sure how much of a difference there was. I'm guessing #ifndef is probably slightly slower than #pragma once, because it has to scan to the end of the file to make sure there is an #endif.
Zifre
It isn't implemented that way. Instead, if the file starts with an #ifndef the first time and ends with an #endif, gcc remembers it and always skips that include in the future without even bothering to open the file.
Jason Coco
Yes, it isn't "much slower" than `#pragma once`. It's identical. The only benefit is avoiding the `stat` syscall, which admittedly can add up during C++ compilation.
Tom
+4  A: 

Using '#pragama 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.

Jonathan Leffler
+2  A: 

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).

Michael Burr
A: 

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).

Klaim
Does Visual Studio not optimize #include guards as-is? Other (better?) compiler do so, and I imagine it is quite easy.
Tom
A: 

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.

Tim Post
+5  A: 

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.

Augusto Radtke
I dislike #pragma once, but I appreciate you pointing out the relative benefits... C++ parsing is much more expensive than anything else, in a "normal" operating environment. Nobody compiles from a remote filesystem if compile-times are an issue.
Tom
Re C++ parsing slowness vs. C#. In C# you don't have to parse (literally) thousands of LOC of header files (iostream, anyone?) for each tiny C++ file. Use precompiled headers to make this problem smaller, however
Eli Bendersky
+7  A: 

#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 due to the way our build system works) then the compiler will think these are different files.

Motti
a-hah! The #1 gotcha!
Tom
But you can also have two files with the same name in different locations without having to bother creating different #define NAMES, which is iften in the form of HEADERFILENAME_H
Vargas
A: 

Does anyone know if the #ifndef has to be first line of the header to work, or will it also work if comments preceed it?

eg.

#ifndef HEADERFILE_H
#define HEADERFILE_H
/* Large comment block
   ...
 */
...
#endif

vs.

/* Large comment block
   ...
 */
#ifndef HEADERFILE_H
#define HEADERFILE_H
...
#endif
Dan G
Doesn't matter. It is a simple preprocessor conditional block, the preprocessor ignores anything it doesn't recognize.
iconiK
#ifndef works anywhere. It's just an `if` block.
Brendan Long
The compiler generally strips comments before attempting anyting else, so you're good there. Read up on the GCC precompiled headers documentation (sorry, I don't remember where I found it... it's googleable). It describes what is required there, which aligns with what you can also expect from #include guard optimization.
Tom
@Brendan: By work, I mean trigger the equivalent "#pragma once" logic. GCC docs examples shows #ifndef as first line.
Dan G
I don't know about other compilers, but GCC's #include-guard optimization still works if there are comments outside the #ifndef block. You can't have anything *else* outside, though; in particular, the OP put their #pragma once outside, that could easily _break_ the optimization in a compiler that supported the optimization but not #pragma once.
Zack
A: 

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.

iconiK