347

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?

Ryan Emerle
  • 14,410
  • 8
  • 47
  • 67
  • 3
    After asking a [similar question](http://stackoverflow.com/questions/4873971/visual-studio-2008-class-view-missing-classes), I found out that `#pragma once` appears to avoid some class view issues in VS 2008. I'm in the process of getting rid of include guards and replacing them all with `#pragma once` for this reason. – SmacL Feb 02 '11 at 13:54

15 Answers15

344

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

Motti
  • 99,411
  • 44
  • 178
  • 249
  • 39
    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 Jul 30 '10 at 12:39
  • 77
    You can also have two or more files with the the same #define WHATEVER which causes no end of fun, which is the reason I would favour using pragma once. – Chris Huang-Leaver Sep 21 '11 at 14:52
  • 123
    Not persuasive... Change the build system to one that doesn't copy files around but uses symlinks instead, or include the same file only from one location in each translation unit. Sounds more like your infrastructure is a mess that has to be reorganized. – Yakov Galka May 11 '12 at 19:04
  • 1
    Wow, I've wasted a couple of days on this. Came to that conclusion, and glad to see it's confirmed. – Yochai Timmer Jan 20 '13 at 09:04
  • 4
    And if you have different files with the same name on different directories, the #ifdef approach will think they are the same file. So there is a drawback for one, and there is a drawback for the other. – rxantos Apr 24 '14 at 04:50
  • 3
    @rxantos, if the files differ the `#ifdef` macro value can also differ. – Motti Apr 24 '14 at 06:59
  • Isn't this more of a drawback of the `#ifndef` include-guard approach? It seems to me that including a given header twice is usually a safer situation to be in (e.g. nothing bad could happen) than to fail to include one of two different headers (something probably will stop working). – Steven Lu Aug 30 '15 at 00:37
  • 1
    @stevenlu what actually happens is sometimes the projects are setup such that the headers are automatically copied to a common folder and marked read-only. In this case, they are the same file and errors related to multiple symbols can waste a lot of time. Speaking from experience :) – Samaursa Dec 16 '15 at 04:40
  • For sure the build settings are always convoluted in a project of almost any appreciable maturity :) --- hopefully soon with modules we can move into a more enlightened age – Steven Lu Dec 16 '15 at 04:42
  • 2
    @rxantos Mostly a non-issue. Many projects, my own included, use **SUBSYSTEM_HEADERNAME_H**, not merely **HEADERNAME_H** (for example, **COMMON_CONTAINERS_GRID_H** or **ENGINE_LOGIC_GAMESTATE_H** (both follow **Binary_Subsystem_File** in my multi-binary project)). Having two identical filenames *in the same subsystem* is much less likely to occur, and if it does occur, there's a good chance someone wrote something redundant, and you'd *want* to know about it. – Jamin Grey Oct 02 '16 at 02:52
  • I should've said, "Some projects", not "many", as I'm really not sure how many use that method and the exaggeration of usage was not warranted. =P – Jamin Grey Oct 02 '16 at 02:58
  • I see this as advantage, because one can have the same file in different namespaces (each with its own directory) and it would work. – nulleight Oct 26 '16 at 12:35
218

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.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Zifre
  • 24,944
  • 8
  • 81
  • 102
  • 13
    It shouldn't be any slower at all (with GCC anyway). – Jason Coco Apr 24 '09 at 21:07
  • 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 Apr 24 '09 at 21:11
  • 56
    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 Apr 25 '09 at 01:32
  • 4
    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 Mar 04 '10 at 06:01
  • 13
    `#pragma once` is generally faster because file is not being preprocessed. `ifndef/define/endif` requires preprocessing anyway, because after this block you can have something compilable (theoretically) – Andrey Mar 03 '11 at 21:57
  • 15
    GCC docs on the guard macro optimization: http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html – Adrian May 17 '11 at 15:31
  • 52
    To use include guards, there is the extra requirement that you must define a new symbol such as `#ifndef FOO_BAR_H`, normally for a file such as "foo_bar.h". If you later rename this file, should you adjust the include guards accordingly to be consistent with this convention? Also, if you have two distinct foo_bar.h's in two different places in your code tree, you have to think of two different symbols for each one. Short answer is to use `#pragma once` and if you really need to compile in an environment that doesn't support it, then go ahead and add include guards for that environment. – Brandin Jun 22 '14 at 07:45
  • 9
    How about name collisions as the reason? – Serg Sep 29 '14 at 13:42
  • 2
    The Solaris compilers also implement the guard macro optimisation: ["Many compilers, including Sun Studio 11, will recognize the typical include guards and never open the file a second time."](http://www.oracle.com/technetwork/server-storage/solaris10/content-142295.html) – Jonathan Wakely Mar 17 '15 at 11:37
  • @Andrey: A smart compiler will flag the file as not having to be processed again (unless the defined preprocessor symbol has been undef'ed). – HelloGoodbye Sep 03 '15 at 20:06
  • 4
    The old Guard using #ifndef raise an issue that does not exists with **#pragma once**, we also have to type the matching #endif. This can lead to some trouble if we are also using other #ifdef in the same header file. If any #endif is forgotten the error will appear in the wrong file and may be quite annoying to find. Another trouble is if dev incorrectly types the same guard for two files (of course it can't happen developper are perfects). In some settings this one can even go unoticed for some time (if no compilation unit use both headers). No such troubles with #pragma once – kriss Jul 21 '16 at 16:45
  • 1
    Just a note: If you're using an IDE like *VS* or *Eclipse* **the compiler isn't the only thing to worry about**. I find `#define` guards can overpopulate the list and these can be mildly annoying when searching for symbols in very large projects. – c z Aug 03 '16 at 13:31
  • didn't #pragma once originate at microsoft? – jcarpenter2 Feb 09 '17 at 06:58
  • 1
    #ifndef include guards will fail if you have two files with the same name, which can often happen in libraries. If library A has "array.h" and B has "array.h", both probably will have ARRAY_H as an include guard, so one of them will be excluded by accident. – Kit10 Mar 16 '18 at 16:25
68

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
  • 311,791
  • 49
  • 497
  • 724
  • 53
    What I really want is a standard `#import` directive. – John Jul 19 '13 at 15:21
  • 12
    A standard import directive is coming: http://isocpp.org/blog/2012/11/modules-update-on-work-in-progress-doug-gregor But not here yet. I am strongly in support of it. – AHelps Apr 03 '15 at 18:34
  • 8
    @AHelps Vaporware. Has it been almost five years now. Maybe in 2023 you'll come back to this comment and say "I told you so". – doug65536 Dec 10 '16 at 10:28
  • It's not vaporware, but it's only at the Technical Specification stage. Modules are implemented in Visual Studio 2015 (https://blogs.msdn.microsoft.com/vcblog/2015/12/03/c-modules-in-vs-2015-update-1/) and in clang (http://clang.llvm.org/docs/Modules.html). And it's import, not #import. – AHelps Dec 14 '16 at 17:15
  • 1
    Should make it into C++20. – Ionoclast Brigham Sep 02 '17 at 04:22
  • 1
    ... and has made it into C++20. – LNJ Jun 29 '20 at 09:02
  • It might still be vaporware even though it's in C++20 https://vector-of-bool.github.io/2019/01/27/modules-doa.html – beauxq Oct 19 '20 at 01:59
41

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.

Community
  • 1
  • 1
JaredPar
  • 673,544
  • 139
  • 1,186
  • 1,421
26

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.

uceumern
  • 730
  • 6
  • 12
12

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.

Edwin Jarvis
  • 5,430
  • 6
  • 33
  • 41
  • 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 Mar 04 '10 at 06:03
  • 1
    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 Oct 28 '10 at 16:55
11

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.

Jesse Beder
  • 30,017
  • 18
  • 97
  • 140
Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
  • 1
    I disagree that you have to support guards anyway. If you use #pragma once (or guards) this is because it raises some conflicts without them. So if it is not supported by your chain tool the project just won't compile and you are exactly in the same kind of situation than when you want to compile some ansi C on an old K&R compiler. You just have to get a more up to date chaintool or change code to add some guards. All hell breaking would be if program was compiling but failed to work. – kriss Jul 21 '16 at 16:56
5

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
  • 60,771
  • 31
  • 121
  • 186
  • Does Visual Studio not optimize #include guards as-is? Other (better?) compiler do so, and I imagine it is quite easy. – Tom Mar 04 '10 at 06:11
  • 2
    Why do you put the `pragma` after the `ifndef`? Is there a benefit? – user1095108 May 13 '14 at 23:04
  • 1
    @user1095108 Some compilers will use the header guards as delimiter to know if the file contain only code that have to be instantiated once. If some code is outside the header guards, then the whole file might be considered maybe instantiable more than once. If that same compiler don't support pragma once, then it will ignore that instruction. Therefore, putting the pragma once inside the header guards is the most generic way to make sure that at least header guards can be "optimized". – Klaim May 14 '14 at 10:52
4

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

Omer
  • 59
  • 1
  • 2
  • 11
    That would be a bug in the compiler. (trying to take a shortcut it shouldn't take). – rxantos Apr 24 '14 at 04:47
  • 4
    `#pragma once` is nonstandard, so whatever a compiler decides on doing is "correct". Of course, then we can start talking about what is "expected" and what is "useful". – user7610 Jan 09 '16 at 21:32
2

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.

gsamaras
  • 66,800
  • 33
  • 152
  • 256
raidsan
  • 743
  • 1
  • 7
  • 11
2

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.

CMircea
  • 3,484
  • 2
  • 32
  • 57
  • 19
    Isn't the benefit that it's much less typing? – Andrey Sep 01 '11 at 23:20
  • 1
    Do note that some milliseconds a hundred thousand times are some minutes, though. Large projects consist of ten thousands of files including tens of headers each. Given present-day many-core CPUs, input/output, _in particular opening many small files_, is one of the major bottlenecks. – Damon Sep 14 '13 at 14:02
  • 1
    _"Today old-school include guards are as fast as a #pragma once."_ Today, and also many many years ago. The oldest docs on the GCC site are for [2.95](https://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC8) from 2001 and optimising include guards was not new then. It isn't a recent optimisation. – Jonathan Wakely Mar 17 '15 at 11:33
  • 4
    The main benefit is that include guards are error-prone and wordy. It's too easy to have two different files with identical names in different directories (and the include guards might be the same symbol), or to make copy-paste errors while copying include guards. Pragma once is less error-prone, and works on all the major PC platforms. If you can use it, it is better style. – AHelps Apr 03 '15 at 18:38
  • _Opening a file is dirt cheap today._ Oh hoh hoh. Try to build a large project from a network mount sometime :) – Martin Cejp May 17 '21 at 10:36
2

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
  • 32,014
  • 15
  • 104
  • 162
2

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.

Shammi
  • 481
  • 5
  • 13
  • 1
    _"That said, these days compilers (including GCC) are smart enough to treat include guards like pragma once."_ They been doing it for decades, maybe longer than `#pragma once` has existed! – Jonathan Wakely Mar 17 '15 at 11:30
  • Think you misunderstood me. I meant to say prior to pragma once, all compilers would incur multiple IO penanties for the same h file included multiple times during the preprocessor stage. Modern implementations end up using better caching of files in the preprocessor stage. Regardless, without pragmas, the preprocessor stage ends up still including everything outside of the include guards. With pragma once, the whole file is left out. From that standpoint, pragma is still advantageous. – Shammi Mar 18 '15 at 15:14
  • 1
    No, that's wrong, decent compilers leave the whole file out even without #pragma once, they don't open the file a second time and they don't even look at it a second time, see https://gcc.gnu.org/onlinedocs/cpp/Once-Only-Headers.html (this is nothing to do with caching). – Jonathan Wakely Mar 18 '15 at 16:03
  • 1
    From your link, seems like the optimization happens only in cpp. Regardless, caching does come into play. How does the preprocessor know to include code outside of the guards. Example... extern int foo; #ifndef INC_GUARD #define INC_GUARD class ClassInHeader{}; #endif In this case the preprocessor will have to include extern int foo; multiple times if you include the same file multiple times. End of the day, not much point arguing over this as long as we understand the difference between #pragma once and include guards and how various compilers behave with both of them :) – Shammi Mar 19 '15 at 17:21
  • 1
    It doesn't apply the optimisation in that, obviously. – Jonathan Wakely Mar 19 '15 at 17:48
1

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.

Marcel
  • 97
  • 1
  • 7
  • Could C++ templates solve the problem? I rarely find any valid need for macros because of how C++ templates. – Clearer Dec 15 '17 at 11:27
  • 2
    Our long term professional experience is that using mature language, software and tools infrastructure all the time gives us as service providers (Embedded Systems) a huge advantage in productivity and flexibility. Competitors developing C++ based embedded systems software and stacks instead might find some of their developers more happy at work. But we usually outperform them time-to-market, functionality and flexibility-wise multiple times. Nether underestimate productivity gains from using one and the same tool over and over again. Web-Devs instead do suffer from ways to many Frameworks. – Marcel Dec 19 '17 at 10:34
  • A note though: isn't including guards/#pragma once in every header file against the DRY principle itself. I can see your point in the `X-Macro` feature, but it is not the main use of include, shouldn't it be the other way around like header unguard/#pragma multi if we were to stick with DRY? – caiohamamura Feb 13 '20 at 14:00
  • DRY stands for "Dont repeat YOURSELF". Its about the human. What the machine is doing, has nothing to do with that paradigm. C++ templates repeat a lot, C-compilers do that as well (e.g. loop unrolling) and every Computer is repeating nearly everything unbelievable often and fast. – Marcel Mar 02 '20 at 09:30
1

I use #ifndef/#define include guards using symbols that incorporate a UUID like this:

#ifndef ARRAY__H_81945CB3_AEBB_471F_AC97_AB6C8B220314
#define ARRAY__H_81945CB3_AEBB_471F_AC97_AB6C8B220314 /* include guard */


#endif

I'v always used editors that were able to generate the UUIDs automatically. This prevents name clash with files with the same base name from other libraries, and detects if the exact same file is placed in multiple locations inside the file system.

The down-side is the increase table size since the symbols are much bigger but I have not yet seen problems with it.

PRouleau
  • 21
  • 1
  • It's also possible to incorporate other elements in the name, such as the library name, the organization name, the creation date. These would be generated automatically and would reduce the probability, already very small, of a clash. – PRouleau May 30 '21 at 00:55