使用#pragma一次有什么危险?

时间:2017-12-15 10:42:17

标签: c++ c macros

现代C和C ++编译器支持非标准#pragma once预处理程序指令,它与经典标题保护程序的用途相似:

#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方法会出现同样的问题,但不允许多次包含标题。

经典方法的另一个问题是,您可能会意外地在不相关的地方定义相同的宏,因此要么不包括预期的标题,要么做一些其他令人讨厌的东西,我无法想象。这在实践中相当容易避免,通过遵守某些约定,例如将宏基于类似UUID的对象(即随机字符串)或(不太理想的方法),基于文件的名称,它们在

在现实生活中,我很少遇到任何这些潜在问题,所以我并不认为它们是主要问题。

#pragma once我能想到的唯一潜在的现实生活问题是,它不是标准的东西 - 你依赖的东西可能无处不在,即使在实践中,它存在于任何地方(*)。

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

(*)只有少数人使用的一些次要编译器,被排除在外。

3 个答案:

答案 0 :(得分:8)

使用#pragma once时遇到的一个问题是包含位于多个位置的同一文件。对于#pragma once,它被认为是不同的,而不是#ifndef/#define后卫。

答案 1 :(得分:4)

到目前为止,我使用过一套不错的编译器:

  • GCC
  • 锵/ LLVM
  • IBM XLC
  • 英特尔C ++编译器

唯一不支持#pragma once的编译器是IBM XLC编译器,它甚至不支持C ++ 11,所以我不感兴趣。如果您需要使用Blue Gene / Q上的IBM XLC Compiler,那么就不能使用#pragma once

很久以前,某些编译器不理解include guard成语,并且会重复打开头文件,但却发现预处理器将内容减少为空。使用这些编译器,使用#pragma once可以提高编译时间。但是,这已在主要编译器中实现,因此现在没有任何区别。

也许您的嵌入式系统有一些特殊的编译器。那个人可能无法使用#pragma once

一般情况下,我更喜欢#pragma once,因为当您复制头文件以通过复制或扩展类进行增量重构时,您不能忘记更改包含保护宏的名称。

因此,除了某些编译器之外,我不知道您对#pragma once有任何难题。

答案 2 :(得分:4)

在使用#pragma once时,您放弃了可移植性。您不再编写C或C ++,而是允许将其作为编译器扩展。

如果您的代码定位到不同的平台,那么可能会让您头疼。

因为这个原因,我从不使用它。

鉴于文件的名称和位置是唯一的,我将其用作我的包含守卫。此外,因为我过去的目标是非常老的预处理器,所以我习惯使用

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

自1996年以来我所遇到的每个平台都有效。