What are the dangers of using #pragma once? [duplicate]

匿名 (未验证) 提交于 2019-12-03 01:39:01

问题:

This question already has an answer here:

Modern C and C++ compilers support the non-standard #pragma once, preprocessor directive, which serve a similar purpose to the classic header guards:

#ifndef hopefully_unique_identifier_that_doesnt_hurt_the_code #define hopefully_unique_identifier_that_doesnt_hurt_the_code   // some code here #endif 

One problem, I'm aware of, with the classic approach is that once you've included a header, you have to #undef the header guard macro to include it again (doing so, to me, is a major code-smell, but that's beside the point here). The same problem arises with the #pragma once approach, but without the possibility of allowing the header to be included more than once.

Another problem with the classic-approach is that you may, accidentally, define the same macro in unrelated places, thus either not including the header as expected or doing some other nasty stuff, that I can't imagine. This is reasonably easy to avoid in practice, by keeping to certain conventions such as basing the macros to UUID-like objects (i.e. random strings) or (the less optimal approach), basing them on the name of the file, they are defined in.

I have only rarely experienced any of these, potential problems, in real life, so I don't really consider them to be major problems.

The only potential real life problem I can think of with #pragma once, is that it's not a standard thing -- you're relying on something that may not be available everywhere, even if it is present, in practice, everywhere (*).

So, what potential problems exist with #pragma once, besides the ones I've already mentioned? Am I having too much faith in having it available, in practice, everywhere?

(*) Some minor compiler that only a handful of people use, excluded.

回答1:

One problem I have encountered with using #pragma once was when including the same file that is located at multiple locations. With #pragma once it is deemed different, not with #ifndef/#define guard.



回答2:

In using #pragma once you are giving up portability. You are no longer writing C or C++, but something allowed as a compiler extension.

That could cause you headaches if your code ever targets a different platform.

It's for this reason that I never use it.

Given that the name and location of a file is unique, I use that as my include guard. Furthermore because I have in the past targetted very old preprocessors, I use as a habit

#if !defined(foo) #define foo 1 /*code*/ #endif 

which has worked on every platform I've encountered since 1996.



回答3:

I have worked with a decent set of compilers so far:

  • GCC
  • Clang/LLVM
  • IBM XLC
  • Intel C++ Compiler

The only compiler that does not support #pragma once is the IBM XLC compiler, that that one does not even support C++11, so I am not interested. If you need to work with the IBM XLC Compiler on Blue Gene/Q, then you cannot use #pragma once.

A long time ago, certain compilers did not understand the include guard idiom and would repeatedly open the header file only to find that the preprocessor reduced the content to nothing. With these compilers, using #pragma once would give compile time benefit. However, this has been implemented in major compilers, such that this makes no difference nowadays.

Perhaps you have some special compiler for your embedded system. That one might be unable to use #pragma once.

In general I prefer #pragma once because when you duplicate a header file in order to do incremental refactoring by duplication or extending a class, you cannot forget to change the name of the include guard macro.

Therefore I do not know of any hard problem you have with #pragma once, except for certain compilers.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!