使用#pragma一次有什么危险? [重复]

问题描述 投票:3回答:3

这个问题在这里已有答案:

现代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还存在哪些潜在的问题?我是否过于相信在实践中,无处不在?

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

c++ c macros
3个回答
8
投票

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


4
投票

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

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

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

鉴于文件的名称和位置是唯一的,我将其用作我的包含守卫。此外,因为我过去曾经针对很老的预处理器,所以我习惯了

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

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


4
投票

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

  • GCC
  • Clang / 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有任何难题。

© www.soinside.com 2019 - 2024. All rights reserved.