#pragma once vs #ifndef

Started by
13 comments, last by SeaBourne 13 years, 2 months ago
I have been reading up on the two differences and require a little conversation to get a better idea as to why I would use one over the other since what I find isn't that helpful. Mainly why I would use #pragma once over #ifndef or both together. It appears that using both would be benificial as well, taking advantage of any optimizations the compiler may have and for writing portable code. A better insight on this would be appreciated.
Advertisement
"#pragma once" is non-standard, meaning the compiler is absolutely allowed to ignore it, so IMO you should use "#pragma once" first (due to it being a compiler optimisation), but also use include guards (#ifndef x, #define x, #endif) as a backup.

In reality though, every modern C++ compiler does support "#pragma once", so it's pretty safe to leave out the traditional include guards.
#pragma once is not, strictly speaking, portable. #ifndef guards usually are, if properly implemented (that is if you're not using reserved symbols for the guard). It doesn't really matter in general. I almost never use #pragma once.
IMO you should use "#pragma once" first (due to it being a compiler optimisation)

Is it an optimisation though? Last time I investigated, MSVC was just as fast with portable scope guards as it was with #pragma once. I presume they accomplish that by applying the same optimization to scope guards as they do to #pragma once (it's essentially the same, with the additional detail that you have to store a mapping of file paths to scope guard names rather than just file paths - but it isn't tricky).
It is an optimisation, but only technically.

The idea is that the compiler can load the file into RAM and once it sees #pragma once it can stop there and go check if it has been included already. Whereas for the traditional way it has to parse the file looking for matching compiler directives until it finds the correct terminating #endif at the bottom.

In practice it's never made a noticeable difference ime and I've worked on fairly large projects using both methods. Nowadays we use the traditional way, as it's absolutely guaranteed to still work on some of the crappier compilers our work often sees us faced with.After all, it's hardly a hassle.
------------------------------Great Little War Game

It is an optimisation, but only technically.

The idea is that the compiler can load the file into RAM and once it sees #pragma once it can stop there and go check if it has been included already. Whereas for the traditional way it has to parse the file looking for matching compiler directives until it finds the correct terminating #endif at the bottom.

In practice it's never made a noticeable difference ime and I've worked on fairly large projects using both methods. Nowadays we use the traditional way, as it's absolutely guaranteed to still work on some of the crappier compilers our work often sees us faced with.After all, it's hardly a hassle.


That's right. There's an article out there with numbers. The difference between #ifdef and #pragma once is not noticeable and often not even measurable.
More effective ways to speed up compilations times are:
* Minimizing your header dependencies
* Precompiled headers
* Big cpp method (#include all .cpps into one big .cpp and compile that. Speeds up linking as well, but only good for complete rebuilds and may have side effects when depending on compilation unit scopes)
* ccache or similar
* distributed compilation
Portability is only one issue. What is more important for me is that #pragma once doesn't allow including a very certain file twice given its location. This little detail may seem unimportant, but let's just imagine you are using some version control that allows sharing files among different directories. It is then tempting to copy some commonly used headers to different modules of the application (different projects in MSVC terminology). Now just imagine following situation:

file A.cpp includes some shared header from A location - G.h, but also includes some header from other module (fe. DLL) - D.h.
Unfortunately file D.h includes the same shared header, but from D location - G.h
Please note that G.h is finally included twice when compiling A.cpp, but each time from a different location, so they are 2 distinct files on a hard drive.

In such a case using #pragma once will result in including this G.h file twice and probably resulting in some redefinition errors, while using #ifndef will work as expected (even though they are 2 distinct files, their content is the same, so name of preprocessor definition is exactly the same).

That's generally why I have switched to using #ifndef... #define... #endif guards from #pragma once

'Rubicon' said:

It is an optimisation, but only technically.

The idea is that the compiler can load the file into RAM and once it sees #pragma once it can stop there and go check if it has been included already. Whereas for the traditional way it has to parse the file looking for matching compiler directives until it finds the correct terminating #endif at the bottom.

In practice it's never made a noticeable difference ime and I've worked on fairly large projects using both methods. Nowadays we use the traditional way, as it's absolutely guaranteed to still work on some of the crappier compilers our work often sees us faced with.After all, it's hardly a hassle.


That's right. There's an article out there with numbers. The difference between #ifdef and #pragma once is not noticeable and often not even measurable.
More effective ways to speed up compilations times are:
* Minimizing your header dependencies
* Precompiled headers
* Big cpp method (#include all .cpps into one big .cpp and compile that. Speeds up linking as well, but only good for complete rebuilds and may have side effects when depending on compilation unit scopes)
* ccache or similar
* distributed compilation


gcc claims to have optimized code for traditional include guards, and I have no reason to not believe it. So if there is a big difference, then prolly on compilers that don't optimize #ifndef-guards :)

Portability is only one issue. What is more important for me is that #pragma once doesn't allow including a very certain file twice given its location. This little detail may seem unimportant, but let's just imagine you are using some version control that allows sharing files among different directories. It is then tempting to copy some commonly used headers to different modules of the application (different projects in MSVC terminology). Now just imagine following situation:

file A.cpp includes some shared header from A location - G.h, but also includes some header from other module (fe. DLL) - D.h.
Unfortunately file D.h includes the same shared header, but from D location - G.h
Please note that G.h is finally included twice when compiling A.cpp, but each time from a different location, so they are 2 distinct files on a hard drive.

In such a case using #pragma once will result in including this G.h file twice and probably resulting in some redefinition errors, while using #ifndef will work as expected (even though they are 2 distinct files, their content is the same, so name of preprocessor definition is exactly the same).

That's generally why I have switched to using #ifndef... #define... #endif guards from #pragma once


A much better solution is to move common headers into a "shared" path such that you can therefore keep track of where exactly you reuse such files. This also helps clean up source control a bit, and makes maintaining compatibility between APIs/clients much easier, since any change in the shared path is guaranteed to break all clients.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


A much better solution is to move common headers into a "shared" path such that you can therefore keep track of where exactly you reuse such files. This also helps clean up source control a bit, and makes maintaining compatibility between APIs/clients much easier, since any change in the shared path is guaranteed to break all clients.

I definitely agree, just wanted to point out that there can be such approach to code organization due to for example SourceSafe possibilities (seems quite common from my own experience despite the fact I think it's messy) and #pragma once just doesn't go together with it.

This topic is closed to new replies.

Advertisement