The [include] guard trick does impose a slight performance penalty ...
(unless the compiler is smart enough to recognize it and
optimize it out). Using "#pragma once" can avoid this overhead
(assuming the compiler is always right about whether it's already seen
a given header -- think about symlinks) at the expense of portability.
For what it is worth, gcc -- which is perhaps the main compiler for
which "#pragma once" is used -- *also* does precisely the above
"optimizing out".
I have not looked at the gcc preprocessor code in a while, but
it would be quite reasonable for it to have a data structure
containing a "system unique file ID" (mount point and inode on
a Unix-like system) and "once-only" flag:
struct include_file_info {
md_fileid_type file_id;
int onceonly;
...
};
Then, "#pragma once" sets:
file->onceonly = 1;
but so does "#ifndef GUARD / #define GUARD / ... / #endif", using
one more field in the "include file info":
file->guard_id = identifier_name;
Now "#include" processing just does:
fi = lookup_file_info(...);
if (fi != NULL &&
(fi->onceonly || (fi->guard_id && cpp_ifdef(fi->guard_id))))
... skip the file ...
which means that "#pragma once" is only very slightly more efficient
anyway (because the #ifndef identifier need not be looked up).
Using "#pragma once" in combination with the guard trick is probably
reasonable if you're careful about it; a compiler that doesn't
recognize "#pragma once" is required to ignore it.
Perhaps; but what about a compiler for which this means "turn on
ce", as opposed to "#pragma offce" (turning off C.E., whatever that
is)?
(GCC1 used to recognize *all* #pragma constructs, treating
them as requests to run rogue or nethack.)