使用#pragma once 有什么危险?

2022-01-11 00:00:00 c macros c++

现代 C 和 C++ 编译器支持非标准的 #pragma once,预处理器指令,其作用与经典的标头保护类似:

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

我知道,使用经典方法的一个问题是,一旦包含标头,您必须 #undef 标头保护宏以再次包含它(这样做,对我来说,这是一个主要的代码气味,但这不是重点).#pragma once 方法也会出现同样的问题,但不可能多次包含标头.

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.

经典方法的另一个问题是,您可能不小心在不相关的地方定义了相同的宏,因此要么没有按预期包含标题,要么做了一些我无法想象的令人讨厌的事情.这在实践中很容易避免,通过遵守某些约定,例如将宏基于类似 UUID 的对象(即随机字符串)或(不太理想的方法),基于文件名,它们在.

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.

#pragma once 我能想到的唯一潜在的现实生活问题是,它不是一个标准的东西――你所依赖的东西可能并非随处可用,即使它实际上,无处不在 (*).

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

那么,除了我已经提到的问题之外,#pragma once 还存在哪些潜在问题?我是否过于相信它在实践中无处不在?

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.

推荐答案

我在使用 #pragma once 时遇到的一个问题是包含位于多个位置的同一个文件时.#pragma once 被认为是不同的,而不是 #ifndef/#define 保护.

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.

相关文章