Please tell me what is the difference between the two directives and which one is better to use in the code?
MyClass.h file
# include & lt; iostream & gt;
#include & lt; string & gt;
#ifndef MYCLASS_H
#define MYCLASS_H
// class description
#endif
Or
# pragma once
#include & lt; iostream & gt;
#include & lt; string & gt;
// class description
Answer 1, authority 100%
The #pragma once
directive is compiler implementation dependent, and therefore may not be supported by individual compilers and will simply be ignored.
The directives #ifndef
and #define
are standard directives, and therefore their use in this context will be the same for all compilers.
Answer 2, authority 96%
The fundamental difference is that #pragma once
refers to the entire header file. The original idea of ​​#pragma once
was that in the process of processing a single translation unit, the compiler (preprocessor) has the right to not even search for or open a second time header files that contain #pragma once
. It was in this form that it was once proposed to standardize #pragma once
as a means of speeding up compilation.
Include guards # ifdef / # endif
, of course, do not have the right to cover the entire header file, i.e. this pair does not generally apply to the entire file. This means that, in general, the compiler will have to find and open the header file to include sections that are not inside # ifdef / # endif
.
At the same time, it is clear that the compiler does not have any difficulty in analyzing the contents of the header file on first reading and recognizing the explicit idiomatic use of # ifdef / # endif
, which scrolls the entire file from beginning to end. In such a situation, #pragma once
provides no practical benefit over # ifdef / # endif
. It is for this reason that the standardization of #pragma once
was abandoned at one time – as a feature that does not bring any additional value (except, perhaps, a compact recording and the fact that, as @vp_arth and @VladD , no need to invent a unique identifier).
Accordingly, the answer is obvious – use the standard functionality # ifdef / # endif
and forget about the non-standard #pragma once
. Maybe in some case you will notice that the compiler (preprocessor) does not want to optimize processing based on the analysis of # ifdef / # endif
and using #pragma once
really speeds up compilation. .. Then, if this is critical for you, it may be worth adding #pragma once
to your files.
Another consideration against the standardization of #pragma once
was that in order to provide a strict guarantee of its specification (that is, strictly a single inclusion), it is necessary to be able to reliably determine the identity of the file as specified in the directive #include
paths. This task is generally extremely difficult to solve in many existing file systems. So beware of naive pioneering statements like “all modern compilers support #pragma once
“. There is no question of any compiler support for a strict specification. And, of course, there is no question of any guarantees of the same behavior between compilers. For this reason, if you are going to use #pragma once
in your code, use it together with include guards, not instead of them.
P.S. Including other header files is usually “put” inside your # ifdef / # endif
. There is no reason for them to be outside. By leaving them outside, you may run the risk of overwhelming the aforementioned optimization. If you already use # ifdef / # endif
, then in the vast majority of cases they should cover the entire file from beginning to end.
Answer 3, authority 98%
Portability
Many compilers that do not support #pragma once
today tend to empty. Basically, there are now undeveloped or abandoned.
The enWiki has a table with links to sources. In this list, only PGI does not support #pragma once
. < br>
Listed on ruWiki OracleSolarisStudio
fixed this omission in version 12.5
Speed ​​up compilation
This plus is very illusive. You may not achieve acceleration of compilation from using it, compilers are able (gcc for sure) to optimize both.
Collisions
The main disadvantage of include guards
is that you cannot guarantee that you have come up with a unique identifier.
If you never plan to include foreign libraries, you can come up with a rule for include guards
and live in peace.
Otherwise, they break everything that C++
namespaces exist for. Simple MYCLASS_H
is clearly not enough, because it may already be defined in another plug-in library, or, if you are writing a library, in the client code.
You have to come up with really unique identifiers, like __VENDOR_PACKAGE_MYCLASS
or __MYCLASS_% TIMESTAMP%
, to avoid collisions.
Resume
Of course, what exactly to use in your project is up to you. However, there is obviously no reason not to use a more concise version other than the fanatical “Not in the standard
“.
PS: You are using include guards
incorrectly – they must cover the entire file as a whole, otherwise the compiler will not be able to optimize them in any way so as not to run the preprocessor for this file again.